* Re: [PATCH v2] i2c-mpc: generate START condition after STOP caused by read i2c_msg
From: Peter Korsgaard @ 2009-05-28 21:08 UTC (permalink / raw)
To: Esben Haabendal; +Cc: Esben Haabendal, linuxppc-dev, linux-i2c, Ben Dooks
In-Reply-To: <d2b9ea600905281341s24efa4e3l6277a8aa5dec5bd@mail.gmail.com>
>>>>> "Esben" == Esben Haabendal <esbenhaabendal@gmail.com> writes:
Hi,
Esben> It's strange, that line looks perfectly fine when I check the
Esben> mail in my GMail inbox and the outbox from the account I sent
Esben> it from.
Well, it is here and in the archive:
http://ozlabs.org/pipermail/linuxppc-dev/2009-May/072274.html
Please consider using git send-email for patches.
--
Bye, Peter Korsgaard
^ permalink raw reply
* Re: [PATCH v2] i2c-mpc: generate START condition after STOP caused by read i2c_msg
From: Esben Haabendal @ 2009-05-28 21:22 UTC (permalink / raw)
To: Peter Korsgaard; +Cc: linuxppc-dev, linux-i2c
In-Reply-To: <87octd5415.fsf@macbook.be.48ers.dk>
Peter Korsgaard wrote:
>>>>>> "Esben" == Esben Haabendal <esbenhaabendal@gmail.com> writes:
>>>>>>
>
> Hi,
>
> Esben> It's strange, that line looks perfectly fine when I check the
> Esben> mail in my GMail inbox and the outbox from the account I sent
> Esben> it from.
>
> Well, it is here and in the archive:
> http://ozlabs.org/pipermail/linuxppc-dev/2009-May/072274.html
>
If you look at
http://www.mail-archive.com/linux-i2c@vger.kernel.org/msg01050.html
instead, the patch is not broken. I find it more likely that the ozlabs.org
archive is breaking my lines, than mail-archive.com putting broken lines
together again.
> Please consider using git send-email for patches.
>
I used git imap-send and thunderbird to do it.
I will consider git send-email in the future, although I don't think
my original e-mail were broken ;-)
But
^ permalink raw reply
* Re: MPC8272- Porting HDLC driver from 2.6.14 to 2.6.27- "no_irq_chip" error
From: Daniel Ng @ 2009-05-29 0:46 UTC (permalink / raw)
To: Wolfram Sang; +Cc: linuxppc-dev@ozlabs.org, Norbert van Bolhuis
In-Reply-To: <20090528123311.GA3112@pengutronix.de>
On Thu, May 28, 2009 at 10:33 PM, Wolfram Sang <w.sang@pengutronix.de> wrote:
>> this is an example of how a simple 8313 Periodic Interval Timer (PIT) kernel driver
>> registers for the PIT IRQ (Interrupt ID 65)
>>
>> #define PIT_IRQ 65
>>
>> virq = irq_create_mapping(NULL, PIT_IRQ);
>> set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
>>
>> if(request_irq(virq, (irq_handler_t)timerEvent, 0, "timer2", (void *)0)) {
>> printk(KERN_ERR "request_irq() returned error for irq=%d virq=%d\n", PIT_IRQ, virq);
>> }
>
> It is some time ago, but when I did something similar I needed the
> following patch in order to use NULL for irq_create_mapping(). Have a
> try, and if it is still needed (as it looks from a glimpse), then maybe
> we should get it merged?
>
> ===
>
> From: Wolfram Sang <w.sang@pengutronix.de>
> Subject: [PATCH] powerpc/cpm2: make cpm2_pic the default host
>
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
> ---
> arch/powerpc/sysdev/cpm2_pic.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
> index 78f1f7c..7a7d4e5 100644
> --- a/arch/powerpc/sysdev/cpm2_pic.c
> +++ b/arch/powerpc/sysdev/cpm2_pic.c
> @@ -272,4 +272,5 @@ void cpm2_pic_init(struct device_node *node)
> printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
> return;
> }
> + irq_set_default_host(cpm2_pic_host);
> }
Thanks guys.
I can confirm that Wolfram's patch above is required to get Norbet's
suggestion to work. Without the patch, I still get the original
symptoms. I have tested this on 2.6.27.19.
Daniel
^ permalink raw reply
* Re: 8544 external interrupt configuration problems
From: Nancy Isaac @ 2009-05-29 1:48 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20090528200215.GA9793@b07421-ec1.am.freescale.net>
[-- Attachment #1: Type: text/plain, Size: 3237 bytes --]
Thank you for your response. My responses below.
On Thu, May 28, 2009 at 1:02 PM, Scott Wood <scottwood@freescale.com> wrote:
> On Thu, May 28, 2009 at 12:05:52PM -0700, Nancy Isaac wrote:
> > My device tree has the following entry for my fpga:
> >
> > CpuCpld\@f0000000{
> > compatible = "MPC8544DS";
> > device_type = "CpuCpld";
> > reg = <f0000000 00000040>;
> > interrupts = <41 2 42 2 43 2>;
> > interrupt-parent = <&mpic>;
> > };
>
> Where did you get those interrupt numbers from? External interrupt
> numbers start at zero on MPIC.
<NI> I tried several things and this is the last set I tried. These
numbers start at the end of the internal interrupts.
I also tried specifying 1, 2 and 3 because it looks like there is just an
array of these interrupts and the interrupts are just added to this array as
they are registered with the hwirq and the virq is the index into the array
where the hwirq was added. I get slightly different results but still not
accurate.
For example, in the device tree, I had setup interrupts = <1 2 2 2 3 2>; for
irq1, 2 and 3 which are all level sensitive interrupts. These map to virq
0x12, 0x13 and 0x14 . I verify that there is no interrupt present by
looking at the registers in the FPGA and also by connecting a scope to the
signal. Immediately after I finish registering the irqs listed above, I get
an interrupt and my print statement in the do_IRQ function returns irq
number 0x12. This happens even if I've disabled the interrupt at the FPGA.
Then I forced an interrupt to occur at the FPGA on irq2 and the do_irq
function still reports that the irq occured for 0x12.
>
> Is the level/sense information correct?
[NI] Yes, these interrupts are supposed to be active low, level sensitive
interrupts.
> > My driver does the mapping to the virq:
> >
> > np = of_find_node_by_type(NULL, "CpuCpld");
> > if (!np) {
> > ret = -ENODEV;
> > }
> > cpldCpuDrv->MateIntIrq = irq_of_parse_and_map(np, 0);
> > cpldCpuDrv->FtaIrq = irq_of_parse_and_map(np, 1);
> > cpldCpuDrv->ExtractIrq = irq_of_parse_and_map(np, 2);
> > cpldCpuDrv->XauiIrq = irq_of_parse_and_map(np, 0);
> >
> > of_node_put(np);
>
> Looks good (other than that you should be using compatible (with a more
> specific name) rather than device_type).
>
> > Does anyone know what the virq should be for these external interrupts?
>
> They're dynamically assigned.
>
> > I've tried specifying the actual irq numbers 1,2 and 3 and that doesn't
> work
> > either.
>
> Specifying them where? In the device tree or as virq numbers? Never
> hard-code virq numbers.
[NI] I specify this in the device tree.
>
>
> > Is there some PCI configuration that's getting in the way? I've tried
> > disabling the FSL_PCIE and I get the same behavior.
>
> Barring an unusual bug, PCI should have nothing to do with the interrupt
> routing of things that aren't on the PCI bus.
[NI]. For 8544, the external interrupts can be shared with PCI Express. I
thought that if I am somehow enabling PCI Express, maybe it would explain
this behavior.
>
>
> -Scott
>
Thanks
Nancy
[-- Attachment #2: Type: text/html, Size: 4659 bytes --]
^ permalink raw reply
* Fwd: serial8250: too much work
From: Alemao @ 2009-05-29 2:57 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <d970ff420905281057kefbf339y29257154c142186a@mail.gmail.com>
Im facing some problems with serial, getting flooded with this
message:
---
serial8250: too much work for irq16
---
Something I notice, in my .dts I have the following lines:
serial0: serial@4500, interrupts =3D <9 =A00x8>
serial1: serial@4600, interrupts =3D <10 0x8>
spi: =A0 =A0 spi@7000, =A0 =A0 interrupts =3D <16 0x8>
But when kernel starts:
---
Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
serial8250.0: ttyS0 at MMIO 0xe0004500 (irq =3D 16) is a 16550A
---
Why IRQ 16? Shouldn't it be IRQ 9?
I traced functions calls in 8250.c driver:
---
serial8250_interrup() -> serial8250_handle_port() -> transmit_chars()
---
"too much work" is for transmiting, but there's nothing to transmit.
In my MPC8343 board I have only serial0 connected to a MAX3232, serial1
is floating. Maybe some electromagnetic interference in the bus?
I found this comments in linux/drivers/serial/8250.h, and tried to use
same defines that they used, but no success:
/*
=A0* Digital did something really horribly wrong with the OUT1 and OUT2
=A0* lines on at least some ALPHA's. =A0The failure mode is that if either
=A0* is cleared, the machine locks up with endless interrupts.
=A0*/
/*
=A0* WindRiver did something similarly broken on their SBC8560 board. The
=A0* UART tristates its IRQ output while OUT2 is clear, but they pulled
=A0* the interrupt line _up_ instead of down, so if we register the IRQ
=A0* while the UART is in that state, we die in an IRQ storm.
=A0*/
I also tried removing serial1 and spi from .dts, but didn't work.
Any sugestions?
Cheers,
--
Alemao
^ permalink raw reply
* Re: [Patch 1/6] Prepare the PowerPC platform for HW Breakpoint infrastructure
From: David Gibson @ 2009-05-29 3:20 UTC (permalink / raw)
To: K.Prasad
Cc: Michael Neuling, Benjamin Herrenschmidt, linuxppc-dev, Alan Stern,
paulus, Roland McGrath
In-Reply-To: <20090525011423.GB11078@in.ibm.com>
On Mon, May 25, 2009 at 06:44:23AM +0530, K.Prasad wrote:
> Prepare the PowerPC code for HW Breakpoint infrastructure patches by including
> relevant constant definitions and function declarations.
>
> Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
> ---
> arch/powerpc/include/asm/hw_breakpoint.h | 57 +++++++++++++++++++++++++++++++
> arch/powerpc/include/asm/processor.h | 1
> arch/powerpc/include/asm/reg.h | 3 +
> 3 files changed, 61 insertions(+)
>
> Index: linux-2.6-tip.hbkpt/arch/powerpc/include/asm/hw_breakpoint.h
> ===================================================================
> --- /dev/null
> +++ linux-2.6-tip.hbkpt/arch/powerpc/include/asm/hw_breakpoint.h
> @@ -0,0 +1,57 @@
> +#ifndef _PPC64_HW_BREAKPOINT_H
> +#define _PPC64_HW_BREAKPOINT_H
> +
> +#ifdef __KERNEL__
> +#define __ARCH_HW_BREAKPOINT_H
> +#ifdef CONFIG_PPC64
> +
> +struct arch_hw_breakpoint {
> + char *name; /* Contains name of the symbol to set bkpt */
> + unsigned long address;
> + u8 type;
You might as well make this an int, it will get padded out to 4 bytes
long anyway.
> +};
> +
> +#include <linux/kdebug.h>
> +#include <asm/reg.h>
> +#include <asm-generic/hw_breakpoint.h>
> +
> +#define HW_BREAKPOINT_READ DABR_DATA_READ
> +#define HW_BREAKPOINT_WRITE DABR_DATA_WRITE
> +#define HW_BREAKPOINT_RW (DABR_DATA_READ | DABR_DATA_WRITE)
> +
> +#define HW_BREAKPOINT_ALIGN 0x7
> +#define HW_BREAKPOINT_LEN INSTRUCTION_LEN
> +
> +extern struct hw_breakpoint *hbp_kernel[HBP_NUM];
> +DECLARE_PER_CPU(struct hw_breakpoint*, this_hbp_kernel[HBP_NUM]);
> +extern unsigned int hbp_user_refcount[HBP_NUM];
> +
> +extern void arch_install_thread_hw_breakpoint(struct task_struct *tsk);
> +extern void arch_uninstall_thread_hw_breakpoint(void);
> +extern int arch_validate_hwbkpt_settings(struct hw_breakpoint *bp,
> + struct task_struct *tsk);
> +extern void arch_update_user_hw_breakpoint(int pos, struct task_struct *tsk);
> +extern void arch_flush_thread_hw_breakpoint(struct task_struct *tsk);
> +extern void arch_update_kernel_hw_breakpoint(void *);
> +extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
> + unsigned long val, void *data);
> +
> +extern void flush_thread_hw_breakpoint(struct task_struct *tsk);
> +extern int copy_thread_hw_breakpoint(struct task_struct *tsk,
> + struct task_struct *child, unsigned long clone_flags);
> +extern void load_debug_registers(void );
It looks as though a lot of these arch hooks ought to have prototypes
in the generic part of the infrastructure.
--
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 2/6] Introduce PPC64 specific Hardware Breakpoint interfaces
From: David Gibson @ 2009-05-29 4:18 UTC (permalink / raw)
To: K.Prasad
Cc: Michael Neuling, Benjamin Herrenschmidt, linuxppc-dev, Alan Stern,
paulus, Roland McGrath
In-Reply-To: <20090525011522.GC11078@in.ibm.com>
On Mon, May 25, 2009 at 06:45:22AM +0530, K.Prasad wrote:
> Introduce PPC64 implementation for the generic hardware breakpoint interfaces
> defined in kernel/hw_breakpoint.c. Enable the HAVE_HW_BREAKPOINT flag and the
> Makefile.
[snip]
> +/* Store the kernel-space breakpoint address value */
> +static unsigned long kdabr;
> +
> +/*
> + * Temporarily stores address for DABR before it is written by the
> + * single-step handler routine
> + */
> +static DEFINE_PER_CPU(unsigned long, dabr_data);
> +
> +void arch_update_kernel_hw_breakpoint(void *unused)
> +{
> + struct hw_breakpoint *bp;
> +
> + /* Check if there is nothing to update */
> + if (hbp_kernel_pos == HBP_NUM)
> + return;
> +
> + per_cpu(this_hbp_kernel[hbp_kernel_pos], get_cpu()) = bp =
> + hbp_kernel[hbp_kernel_pos];
> + if (bp == NULL)
> + kdabr = 0;
> + else
> + kdabr = (bp->info.address & ~HW_BREAKPOINT_ALIGN) |
> + bp->info.type | DABR_TRANSLATION;
> + set_dabr(kdabr);
> + put_cpu_no_resched();
> +}
> +
> +/*
> + * Install the thread breakpoints in their debug registers.
> + */
> +void arch_install_thread_hw_breakpoint(struct task_struct *tsk)
> +{
> + set_dabr(tsk->thread.dabr);
> +}
> +
> +/*
> + * Install the debug register values for just the kernel, no thread.
> + */
> +void arch_uninstall_thread_hw_breakpoint()
> +{
> + set_dabr(0);
> +}
> +
> +/*
> + * Store a breakpoint's encoded address, length, and type.
> + */
> +int arch_store_info(struct hw_breakpoint *bp, struct task_struct *tsk)
> +{
> + /*
> + * User-space requests will always have the address field populated
> + * Symbol names from user-space are rejected
> + */
> + if (tsk && bp->info.name)
> + return -EINVAL;
> + /*
> + * User-space requests will always have the address field populated
> + * For kernel-addresses, either the address or symbol name can be
> + * specified.
> + */
> + if (bp->info.name)
> + bp->info.address = (unsigned long)
> + kallsyms_lookup_name(bp->info.name);
> + if (bp->info.address)
> + return 0;
> + return -EINVAL;
> +}
> +
> +/*
> + * Validate the arch-specific HW Breakpoint register settings
> + */
> +int arch_validate_hwbkpt_settings(struct hw_breakpoint *bp,
> + struct task_struct *tsk)
> +{
> + int is_kernel, ret = -EINVAL;
> +
> + if (!bp)
> + return ret;
> +
> + switch (bp->info.type) {
> + case HW_BREAKPOINT_READ:
> + case HW_BREAKPOINT_WRITE:
> + case HW_BREAKPOINT_RW:
> + break;
> + default:
> + return ret;
> + }
> +
> + if (bp->triggered)
> + ret = arch_store_info(bp, tsk);
> +
> + is_kernel = is_kernel_addr(bp->info.address);
> + if ((tsk && is_kernel) || (!tsk && !is_kernel))
> + return -EINVAL;
> +
> + return ret;
> +}
> +
> +void arch_update_user_hw_breakpoint(int pos, struct task_struct *tsk)
> +{
> + struct thread_struct *thread = &(tsk->thread);
> + struct hw_breakpoint *bp = thread->hbp[0];
> +
> + if (bp)
> + thread->dabr = (bp->info.address & ~HW_BREAKPOINT_ALIGN) |
> + bp->info.type | DABR_TRANSLATION;
> + else
> + thread->dabr = 0;
> +}
> +
> +void arch_flush_thread_hw_breakpoint(struct task_struct *tsk)
> +{
> + struct thread_struct *thread = &(tsk->thread);
> +
> + thread->dabr = 0;
> +}
> +
> +/*
> + * Handle debug exception notifications.
> + */
> +int __kprobes hw_breakpoint_handler(struct die_args *args)
> +{
> + int rc = NOTIFY_STOP;
> + struct hw_breakpoint *bp;
> + struct pt_regs *regs = args->regs;
> + unsigned long dar = regs->dar;
> + int cpu, stepped = 1;
> +
> + /* Disable breakpoints during exception handling */
> + set_dabr(0);
> +
> + cpu = get_cpu();
> + /* Determine whether kernel- or user-space address is the trigger */
> + bp = (hbp_kernel_pos == HBP_NUM) ? current->thread.hbp[0] :
> + per_cpu(this_hbp_kernel[0], cpu);
> + /*
> + * bp can be NULL due to lazy debug register switching
> + * or due to the delay between updates of hbp_kernel_pos
> + * and this_hbp_kernel.
> + */
> + if (!bp)
> + goto out;
> +
> + if (dar == bp->info.address)
> + per_cpu(dabr_data, cpu) = (hbp_kernel_pos == HBP_NUM) ?
> + current->thread.dabr : kdabr;
> + else {
> + /*
> + * This exception is triggered not because of a memory access on
> + * the monitored variable but in the double-word address range
> + * in which it is contained. We will consume this exception,
> + * considering it as 'noise'.
> + */
> + rc = NOTIFY_STOP;
> + goto out;
> + }
> + (bp->triggered)(bp, regs);
This will fire the handler function before the instruction has
executed. I remember seeing a comment in the other patchset saying
the function would be triggered after execution, but I'm not sure if
that was in generic of x86-specific code.
> +
> + stepped = emulate_step(regs, regs->nip);
> + /*
> + * Single-step the causative instruction manually if
> + * emulate_step() could not execute it
> + */
> + if (stepped == 0) {
> + regs->msr |= MSR_SE;
> + goto out;
> + }
> + set_dabr(per_cpu(dabr_data, cpu));
> + per_cpu(dabr_data, cpu) = 0;
This curly arrangement of put_cpu() / get_cpu() could probably do with
some more comments...
> +out:
> + /* Enable pre-emption only if single-stepping is finished */
> + if (stepped)
> + put_cpu_no_resched();
> + return rc;
> +}
> +
> +/*
> + * Handle single-step exceptions following a DABR hit.
> + */
> +int __kprobes single_step_dabr_instruction(struct die_args *args)
> +{
> + struct pt_regs *regs = args->regs;
> + int cpu = get_cpu();
> + int ret = NOTIFY_DONE;
> + siginfo_t info;
> + unsigned long this_dabr_data = per_cpu(dabr_data, cpu);
> +
> + /*
> + * Check if we are single-stepping as a result of a
> + * previous HW Breakpoint exception
> + */
> + if (this_dabr_data == 0)
> + goto out;
> +
> + regs->msr &= ~MSR_SE;
> + /* Deliver signal to user-space */
> + if (this_dabr_data < TASK_SIZE) {
> + info.si_signo = SIGTRAP;
> + info.si_errno = 0;
> + info.si_code = TRAP_HWBKPT;
> + info.si_addr = (void __user *)(per_cpu(dabr_data, cpu));
> + force_sig_info(SIGTRAP, &info, current);
> + }
Ok, this is a behaviour change - the old do_dabr() code fired the
SIGTRAP before the instruction completed, but this will fire it
after. It seems simpler and safer to move this into ptrace's
triggered function.
> +
> + set_dabr(this_dabr_data);
> + per_cpu(dabr_data, cpu) = 0;
> + ret = NOTIFY_STOP;
> + /*
> + * If single-stepped after hw_breakpoint_handler(), pre-emption is
> + * already disabled.
> + */
> + put_cpu_no_resched();
> +
> +out:
> + /*
> + * A put_cpu_no_resched() call is required to complement the get_cpu()
> + * call used initially
> + */
> + put_cpu_no_resched();
> + return ret;
> +}
> +
> +/*
> + * Handle debug exception notifications.
> + */
> +int __kprobes hw_breakpoint_exceptions_notify(
> + struct notifier_block *unused, unsigned long val, void *data)
> +{
> + int ret = NOTIFY_DONE;
> +
> + switch (val) {
> + case DIE_DABR_MATCH:
> + ret = hw_breakpoint_handler(data);
> + break;
> + case DIE_SSTEP:
> + ret = single_step_dabr_instruction(data);
> + break;
> + }
> +
> + return ret;
> +}
--
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 4/6] Modify process and processor handling code to recognise hardware debug registers
From: David Gibson @ 2009-05-29 4:29 UTC (permalink / raw)
To: K.Prasad
Cc: Michael Neuling, Benjamin Herrenschmidt, linuxppc-dev, Alan Stern,
paulus, Roland McGrath
In-Reply-To: <20090525011650.GE11078@in.ibm.com>
On Mon, May 25, 2009 at 06:46:50AM +0530, K.Prasad wrote:
> Modify process handling code to recognise hardware debug registers during copy
> and flush operations. Introduce a new TIF_DEBUG task flag to indicate a
> process's use of debug register. Load the debug register values into a
> new CPU during initialisation.
[snip]
> Index: linux-2.6-tip.hbkpt/arch/powerpc/kernel/process.c
> ===================================================================
> --- linux-2.6-tip.hbkpt.orig/arch/powerpc/kernel/process.c
> +++ linux-2.6-tip.hbkpt/arch/powerpc/kernel/process.c
> @@ -50,6 +50,7 @@
> #include <asm/syscalls.h>
> #ifdef CONFIG_PPC64
> #include <asm/firmware.h>
> +#include <asm/hw_breakpoint.h>
> #endif
> #include <linux/kprobes.h>
> #include <linux/kdebug.h>
> @@ -254,8 +255,10 @@ void do_dabr(struct pt_regs *regs, unsig
> 11, SIGSEGV) == NOTIFY_STOP)
> return;
>
> +#ifndef CONFIG_PPC64
> if (debugger_dabr_match(regs))
> return;
> +#endif
>
> /* Clear the DAC and struct entries. One shot trigger */
> #if defined(CONFIG_BOOKE)
> @@ -372,8 +375,13 @@ struct task_struct *__switch_to(struct t
>
> #endif /* CONFIG_SMP */
>
> +#ifdef CONFIG_PPC64
> + if (unlikely(test_tsk_thread_flag(new, TIF_DEBUG)))
> + arch_install_thread_hw_breakpoint(new);
> +#else
> if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
> set_dabr(new->thread.dabr);
> +#endif /* CONFIG_PPC64 */
>
> #if defined(CONFIG_BOOKE)
> /* If new thread DAC (HW breakpoint) is the same then leave it */
> @@ -550,6 +558,10 @@ void show_regs(struct pt_regs * regs)
> void exit_thread(void)
> {
> discard_lazy_cpu_state();
> +#ifdef CONFIG_PPC64
> + if (unlikely(test_tsk_thread_flag(current, TIF_DEBUG)))
> + flush_thread_hw_breakpoint(current);
> +#endif /* CONFIG_PPC64 */
> }
>
> void flush_thread(void)
> @@ -605,6 +617,9 @@ int copy_thread(unsigned long clone_flag
> struct pt_regs *childregs, *kregs;
> extern void ret_from_fork(void);
> unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
> +#ifdef CONFIG_PPC64
> + struct task_struct *tsk = current;
I don't see any point to adding this variable, just reference current
directly below.
> +#endif
>
> CHECK_FULL_REGS(regs);
> /* Copy registers */
> @@ -672,6 +687,9 @@ int copy_thread(unsigned long clone_flag
> * function.
> */
> kregs->nip = *((unsigned long *)ret_from_fork);
> +
> + if (unlikely(test_tsk_thread_flag(tsk, TIF_DEBUG)))
> + copy_thread_hw_breakpoint(tsk, p, clone_flags);
> #else
> kregs->nip = (unsigned long)ret_from_fork;
> #endif
--
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] powerpc ptrace block-step
From: Benjamin Herrenschmidt @ 2009-05-29 5:03 UTC (permalink / raw)
To: Roland McGrath; +Cc: linuxppc-dev, utrace-devel
In-Reply-To: <20090401215903.DE872FC3AB@magilla.sf.frob.com>
On Wed, 2009-04-01 at 14:59 -0700, Roland McGrath wrote:
> Maynard asked about user_enable_block_step() support on powerpc.
> This is the old patch I've posted before. I haven't even tried
> to compile it lately, but it rebased cleanly.
>
> AFAIK the only reason this didn't go in several months ago was waiting
> for someone to decide what the right arch_has_block_step() condition was,
> i.e. if it needs to check some cpu_feature or chip identifier bits.
>
> I had hoped that I had passed the buck then to ppc folks to figure that out
> and make it so. But it does not appear to have happened.
>
> Note you can drop the #define PTRACE_SINGLEBLOCK if you want to be
> conservative and not touch the user (ptrace) ABI yet. Then Maynard
> could beat on it with internal uses (utrace) before you worry about
> whether userland expects the new ptrace request macro to exist.
So the patch had some issues, such as missing clearing of DBCR0 bits,
missing changes to code in traps.c to properly identify the new cause
of debug interrupts, etc...
I've spinned a new version, I'll post it as soon as I got to do some
quick tests. It will then go into the next merge window hopefully.
Note: I've verified, blockstep seems to be implemented by all the core
variants -except- the old 601.
Cheers,
Ben.
^ permalink raw reply
* [PATCH 1/3] powerpc/ftrace: Use ppc_function_entry() instead of GET_ADDR
From: Michael Ellerman @ 2009-05-29 5:33 UTC (permalink / raw)
To: linuxppc-dev
Use ppc_function_entry() from code-patching.h.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/ftrace.c | 12 +++---------
1 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index 70e2a73..8585217 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -23,12 +23,6 @@
#include <asm/code-patching.h>
#include <asm/ftrace.h>
-#ifdef CONFIG_PPC32
-# define GET_ADDR(addr) addr
-#else
-/* PowerPC64's functions are data that points to the functions */
-# define GET_ADDR(addr) (*(unsigned long *)addr)
-#endif
#ifdef CONFIG_DYNAMIC_FTRACE
static unsigned int ftrace_nop_replace(void)
@@ -41,7 +35,7 @@ ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
{
unsigned int op;
- addr = GET_ADDR(addr);
+ addr = ppc_function_entry((void *)addr);
/* if (link) set op to 'bl' else 'b' */
op = create_branch((unsigned int *)ip, addr, link ? 1 : 0);
@@ -197,7 +191,7 @@ __ftrace_make_nop(struct module *mod,
ptr = ((unsigned long)jmp[0] << 32) + jmp[1];
/* This should match what was called */
- if (ptr != GET_ADDR(addr)) {
+ if (ptr != ppc_function_entry((void *)addr)) {
printk(KERN_ERR "addr does not match %lx\n", ptr);
return -EINVAL;
}
@@ -570,7 +564,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
return_hooker = (unsigned long)&mod_return_to_handler;
#endif
- return_hooker = GET_ADDR(return_hooker);
+ return_hooker = ppc_function_entry((void *)return_hooker);
/*
* Protect against fault, even if it shouldn't
--
1.6.2.1
^ permalink raw reply related
* [PATCH 2/3] powerpc/ftrace: Remove unused macros
From: Michael Ellerman @ 2009-05-29 5:33 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <8e59964be84e85d2ca8c08db3fdd979db61fb0f6.1243575200.git.michael@ellerman.id.au>
These macros were used in the original port, but since commit
e4486fe316 (ftrace, use probe_kernel API to modify code) they
are unused.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/ftrace.c | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index 8585217..8620ecb 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -43,14 +43,6 @@ ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
return op;
}
-#ifdef CONFIG_PPC64
-# define _ASM_ALIGN " .align 3 "
-# define _ASM_PTR " .llong "
-#else
-# define _ASM_ALIGN " .align 2 "
-# define _ASM_PTR " .long "
-#endif
-
static int
ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
{
--
1.6.2.1
^ permalink raw reply related
* [PATCH 3/3] powerpc/ftrace: Use PPC_INST_NOP directly
From: Michael Ellerman @ 2009-05-29 5:33 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <8e59964be84e85d2ca8c08db3fdd979db61fb0f6.1243575200.git.michael@ellerman.id.au>
There's no need to wrap PPC_INST_NOP in a static inline.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/ftrace.c | 9 ++-------
1 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index 8620ecb..f4ad248 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -25,11 +25,6 @@
#ifdef CONFIG_DYNAMIC_FTRACE
-static unsigned int ftrace_nop_replace(void)
-{
- return PPC_INST_NOP;
-}
-
static unsigned int
ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
{
@@ -314,7 +309,7 @@ int ftrace_make_nop(struct module *mod,
if (test_24bit_addr(ip, addr)) {
/* within range */
old = ftrace_call_replace(ip, addr, 1);
- new = ftrace_nop_replace();
+ new = PPC_INST_NOP;
return ftrace_modify_code(ip, old, new);
}
@@ -452,7 +447,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
*/
if (test_24bit_addr(ip, addr)) {
/* within range */
- old = ftrace_nop_replace();
+ old = PPC_INST_NOP;
new = ftrace_call_replace(ip, addr, 1);
return ftrace_modify_code(ip, old, new);
}
--
1.6.2.1
^ permalink raw reply related
* Re: [PATCH] powerpc: tiny memcpy_(to|from)io optimisation
From: Joakim Tjernlund @ 2009-05-29 6:31 UTC (permalink / raw)
To: Albrecht Dreß; +Cc: linuxppc-dev
In-Reply-To: <1243540232.3305.0@antares>
> Am 28.05.09 18:13 schrieb(en) Joakim Tjernlund:
> > hmm, these do look a bit unoptimal anyway. Any reason not to write
> > them something like below(written by me for uClibc long time ago).
> > You will have to add eieio()/sync
>
> No (and I wasn't aware of the PPC pre-inc vs. post-inc stuff) - I just
I think this is true for most RISC based CPU's. It is a pity as
post ops are a lot more common. The do {} while(--chunks) is also
better. Basically the "while(--chunks)" is free(but only if you don't use
chunks inside the loop).
> stumbled over this while fixing mtd accesses to the MPC5200's Local Bus
> in 16-bit mode which doesn't allow byte accesses. And I didn't want to
> go too deep into this as the real fix for me is actually somewhat
> different...
OK.
>
> > /* PPC can do pre increment and load/store, but not post increment
> > and load/store.
> > Therefore use *++ptr instead of *ptr++. */
> [snip]
> > copy_chunks:
> > do {
> > /* make gcc to load all data, then store it */
> > tmp1 = *(unsigned long *)(tmp_from+4);
> > tmp_from += 8;
> > tmp2 = *(unsigned long *)tmp_from;
> > *(unsigned long *)(tmp_to+4) = tmp1;
> > tmp_to += 8;
> > *(unsigned long *)tmp_to = tmp2;
> > } while (--chunks);
>
> Is this the same for all PPC cores, i.e. do they all benefit from
> loading/storing 8 instead of 4 bytes?
As I recall there is an extra cycle between load and store,
so you will benefit from doing all your loads first and then
stores. The kernel memcpy has loads 16 bytes before storing. I selected
8 as uClibc should also be small.
Since there has to be eieio between ops I am not sure it will
matter here. Perhaps it is better to do 4 bytes in the main loop, making
the whole function smaller. There are memset and memmove functions in
uClibc too.
Jocke
^ permalink raw reply
* [RFC/PATCH] From: Roland McGrath <roland@redhat.com>
From: Benjamin Herrenschmidt @ 2009-05-29 7:06 UTC (permalink / raw)
To: linuxppc-dev; +Cc: roland
powerpc: Add PTRACE_SINGLEBLOCK support
Reworked by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This adds block-step support on powerpc, including a PTRACE_SINGLEBLOCK
request for ptrace.
The BookE implementation is tweaked to fire a single step after a
block step in order to mimmic the server behaviour.
Signed-off-by: Roland McGrath <roland@redhat.com>
---
WARNING: There is a difference between the BookE implementations
(that use DBCR0:BT) and the "classic" implementations (that use MSR:BE).
The former will stop -on- the branch that is about to be taken without
actually taking it, while the later will stop on the -target- of the
branch.
The BookE variant is superior in some ways as it allows to know where
you come from on branches. But that also means that the semantics exposed
to user space would not be consistent which is BAD (tm).
I'm not sure what the right approach is. For now, I've made BookE mimmic
server by automatically firing a single step right after the blockstep
from the kernel, so the semantics exposed to userspace are identical,
but that mean we do lose some information in the BookE case that would
have otherwise been available (the branch origin).
Now, some server processors do provide it via an SPR, but I don't know
if we can retrieve it, because I think it could be clobbered by the act
of taking the debug interrupt ... non trivial.
Roland, what do you think is the right approach ? This patch ?
arch/powerpc/include/asm/ptrace.h | 4 ++++
arch/powerpc/kernel/head_booke.h | 10 +++++-----
arch/powerpc/kernel/ptrace.c | 23 +++++++++++++++++++++--
arch/powerpc/kernel/traps.c | 34 ++++++++++++++++++++++++++++++----
4 files changed, 60 insertions(+), 11 deletions(-)
--- linux-work.orig/arch/powerpc/include/asm/ptrace.h 2009-02-05 16:22:24.000000000 +1100
+++ linux-work/arch/powerpc/include/asm/ptrace.h 2009-05-29 14:53:39.000000000 +1000
@@ -135,7 +135,9 @@ do { \
* These are defined as per linux/ptrace.h, which see.
*/
#define arch_has_single_step() (1)
+#define arch_has_block_step() (!cpu_has_feature(CPU_FTR_601))
extern void user_enable_single_step(struct task_struct *);
+extern void user_enable_block_step(struct task_struct *);
extern void user_disable_single_step(struct task_struct *);
#endif /* __ASSEMBLY__ */
@@ -288,4 +290,6 @@ extern void user_disable_single_step(str
#define PPC_PTRACE_PEEKUSR_3264 0x91
#define PPC_PTRACE_POKEUSR_3264 0x90
+#define PTRACE_SINGLEBLOCK 0x100 /* resume execution until next branch */
+
#endif /* _ASM_POWERPC_PTRACE_H */
Index: linux-work/arch/powerpc/kernel/ptrace.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/ptrace.c 2009-02-05 16:22:25.000000000 +1100
+++ linux-work/arch/powerpc/kernel/ptrace.c 2009-05-29 14:31:15.000000000 +1000
@@ -704,15 +704,34 @@ void user_enable_single_step(struct task
if (regs != NULL) {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ task->thread.dbcr0 &= ~DBCR0_BT;
task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
regs->msr |= MSR_DE;
#else
+ regs->msr &= ~MSR_BE;
regs->msr |= MSR_SE;
#endif
}
set_tsk_thread_flag(task, TIF_SINGLESTEP);
}
+void user_enable_block_step(struct task_struct *task)
+{
+ struct pt_regs *regs = task->thread.regs;
+
+ if (regs != NULL) {
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ task->thread.dbcr0 &= ~DBCR0_IC;
+ task->thread.dbcr0 = DBCR0_IDM | DBCR0_BT;
+ regs->msr |= MSR_DE;
+#else
+ regs->msr &= ~MSR_SE;
+ regs->msr |= MSR_BE;
+#endif
+ }
+ set_tsk_thread_flag(task, TIF_SINGLESTEP);
+}
+
void user_disable_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
@@ -726,10 +745,10 @@ void user_disable_single_step(struct tas
if (regs != NULL) {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
- task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_IDM);
+ task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
regs->msr &= ~MSR_DE;
#else
- regs->msr &= ~MSR_SE;
+ regs->msr &= ~(MSR_SE | MSR_BE);
#endif
}
clear_tsk_thread_flag(task, TIF_SINGLESTEP);
Index: linux-work/arch/powerpc/kernel/head_booke.h
===================================================================
--- linux-work.orig/arch/powerpc/kernel/head_booke.h 2009-05-29 14:24:47.000000000 +1000
+++ linux-work/arch/powerpc/kernel/head_booke.h 2009-05-29 14:54:26.000000000 +1000
@@ -256,7 +256,7 @@ label:
* off DE in the DSRR1 value and clearing the debug status. \
*/ \
mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
- andis. r10,r10,DBSR_IC@h; \
+ andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \
beq+ 2f; \
\
lis r10,KERNELBASE@h; /* check if exception in vectors */ \
@@ -271,7 +271,7 @@ label:
\
/* here it looks like we got an inappropriate debug exception. */ \
1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CDRR1 value */ \
- lis r10,DBSR_IC@h; /* clear the IC event */ \
+ lis r10,(DBSR_IC|DBSR_BT)@h; /* clear the IC event */ \
mtspr SPRN_DBSR,r10; \
/* restore state and get out */ \
lwz r10,_CCR(r11); \
@@ -309,7 +309,7 @@ label:
* off DE in the CSRR1 value and clearing the debug status. \
*/ \
mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
- andis. r10,r10,DBSR_IC@h; \
+ andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \
beq+ 2f; \
\
lis r10,KERNELBASE@h; /* check if exception in vectors */ \
@@ -317,14 +317,14 @@ label:
cmplw r12,r10; \
blt+ 2f; /* addr below exception vectors */ \
\
- lis r10,DebugCrit@h; \
+ lis r10,DebugCrit@h; \
ori r10,r10,DebugCrit@l; \
cmplw r12,r10; \
bgt+ 2f; /* addr above exception vectors */ \
\
/* here it looks like we got an inappropriate debug exception. */ \
1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \
- lis r10,DBSR_IC@h; /* clear the IC event */ \
+ lis r10,(DBSR_IC|DBSR_BT)@h; /* clear the IC event */ \
mtspr SPRN_DBSR,r10; \
/* restore state and get out */ \
lwz r10,_CCR(r11); \
Index: linux-work/arch/powerpc/kernel/traps.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/traps.c 2009-05-29 14:32:06.000000000 +1000
+++ linux-work/arch/powerpc/kernel/traps.c 2009-05-29 17:02:35.000000000 +1000
@@ -1041,7 +1041,34 @@ void SoftwareEmulation(struct pt_regs *r
void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
{
- if (debug_status & DBSR_IC) { /* instruction completion */
+ /* Hack alert: On BookE, Branch Taken stops on the branch itself, while
+ * on server, it stops on the target of the branch. In order to simulate
+ * the server behaviour, we thus restart right away with a single step
+ * instead of stopping here when hitting a BT
+ */
+ if (debug_status & DBSR_BT) {
+ regs->msr &= ~MSR_DE;
+
+ /* Disable BT */
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_BT);
+ /* Clear the BT event */
+ mtspr(SPRN_DBSR, DBSR_BT);
+
+ /* Do the single step trick only when coming from userspace */
+ if (user_mode(regs)) {
+ current->thread.dbcr0 &= ~DBCR0_BT;
+ current->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
+ regs->msr |= MSR_DE;
+ return;
+ }
+
+ if (notify_die(DIE_SSTEP, "block_step", regs, 5,
+ 5, SIGTRAP) == NOTIFY_STOP) {
+ return;
+ }
+ if (debugger_sstep(regs))
+ return;
+ } else if (debug_status & DBSR_IC) { /* Instruction complete */
regs->msr &= ~MSR_DE;
/* Disable instruction completion */
@@ -1057,9 +1084,8 @@ void __kprobes DebugException(struct pt_
if (debugger_sstep(regs))
return;
- if (user_mode(regs)) {
- current->thread.dbcr0 &= ~DBCR0_IC;
- }
+ if (user_mode(regs))
+ current->thread.dbcr0 &= ~(DBCR0_IC);
_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
} else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {
^ permalink raw reply
* Re: [RFC][PATCH] powerpc/pci: Pull ppc32 code we need in ppc64
From: Benjamin Herrenschmidt @ 2009-05-29 7:18 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev list
In-Reply-To: <1242803331.16901.188.camel@pasglop>
On Wed, 2009-05-20 at 17:08 +1000, Benjamin Herrenschmidt wrote:
> On Wed, 2009-05-20 at 00:57 -0500, Kumar Gala wrote:
> > Ben,
> >
> > Comments on the pmac case?
>
> Not yet :-) Give me a day. Was tracking a bug today.
A few days later...
Looks good. I had a quick peek at powermac users of the early ops and
they all seem to have a valid "hose".
Cheers,
Ben.
^ permalink raw reply
* [RFC/PATCH] powerpc: Add PTRACE_SINGLEBLOCK support
From: Benjamin Herrenschmidt @ 2009-05-29 7:26 UTC (permalink / raw)
To: linuxppc-dev; +Cc: roland
From: Roland McGrath <roland@redhat.com>
Reworked by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This adds block-step support on powerpc, including a PTRACE_SINGLEBLOCK
request for ptrace.
The BookE implementation is tweaked to fire a single step after a
block step in order to mimmic the server behaviour.
Signed-off-by: Roland McGrath <roland@redhat.com>
---
WARNING: There is a difference between the BookE implementations
(that use DBCR0:BT) and the "classic" implementations (that use MSR:BE).
The former will stop -on- the branch that is about to be taken without
actually taking it, while the later will stop on the -target- of the
branch.
The BookE variant is superior in some ways as it allows to know where
you come from on branches. But that also means that the semantics exposed
to user space would not be consistent which is BAD (tm).
I'm not sure what the right approach is. For now, I've made BookE mimmic
server by automatically firing a single step right after the blockstep
from the kernel, so the semantics exposed to userspace are identical,
but that mean we do lose some information in the BookE case that would
have otherwise been available (the branch origin).
Now, some server processors do provide it via an SPR, but I don't know
if we can retrieve it, because I think it could be clobbered by the act
of taking the debug interrupt ... non trivial.
Roland, what do you think is the right approach ? This patch ?
arch/powerpc/include/asm/ptrace.h | 4 ++++
arch/powerpc/kernel/head_booke.h | 10 +++++-----
arch/powerpc/kernel/ptrace.c | 23 +++++++++++++++++++++--
arch/powerpc/kernel/traps.c | 34 ++++++++++++++++++++++++++++++----
4 files changed, 60 insertions(+), 11 deletions(-)
--- linux-work.orig/arch/powerpc/include/asm/ptrace.h 2009-02-05 16:22:24.000000000 +1100
+++ linux-work/arch/powerpc/include/asm/ptrace.h 2009-05-29 14:53:39.000000000 +1000
@@ -135,7 +135,9 @@ do { \
* These are defined as per linux/ptrace.h, which see.
*/
#define arch_has_single_step() (1)
+#define arch_has_block_step() (!cpu_has_feature(CPU_FTR_601))
extern void user_enable_single_step(struct task_struct *);
+extern void user_enable_block_step(struct task_struct *);
extern void user_disable_single_step(struct task_struct *);
#endif /* __ASSEMBLY__ */
@@ -288,4 +290,6 @@ extern void user_disable_single_step(str
#define PPC_PTRACE_PEEKUSR_3264 0x91
#define PPC_PTRACE_POKEUSR_3264 0x90
+#define PTRACE_SINGLEBLOCK 0x100 /* resume execution until next branch */
+
#endif /* _ASM_POWERPC_PTRACE_H */
Index: linux-work/arch/powerpc/kernel/ptrace.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/ptrace.c 2009-02-05 16:22:25.000000000 +1100
+++ linux-work/arch/powerpc/kernel/ptrace.c 2009-05-29 14:31:15.000000000 +1000
@@ -704,15 +704,34 @@ void user_enable_single_step(struct task
if (regs != NULL) {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ task->thread.dbcr0 &= ~DBCR0_BT;
task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
regs->msr |= MSR_DE;
#else
+ regs->msr &= ~MSR_BE;
regs->msr |= MSR_SE;
#endif
}
set_tsk_thread_flag(task, TIF_SINGLESTEP);
}
+void user_enable_block_step(struct task_struct *task)
+{
+ struct pt_regs *regs = task->thread.regs;
+
+ if (regs != NULL) {
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ task->thread.dbcr0 &= ~DBCR0_IC;
+ task->thread.dbcr0 = DBCR0_IDM | DBCR0_BT;
+ regs->msr |= MSR_DE;
+#else
+ regs->msr &= ~MSR_SE;
+ regs->msr |= MSR_BE;
+#endif
+ }
+ set_tsk_thread_flag(task, TIF_SINGLESTEP);
+}
+
void user_disable_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
@@ -726,10 +745,10 @@ void user_disable_single_step(struct tas
if (regs != NULL) {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
- task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_IDM);
+ task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
regs->msr &= ~MSR_DE;
#else
- regs->msr &= ~MSR_SE;
+ regs->msr &= ~(MSR_SE | MSR_BE);
#endif
}
clear_tsk_thread_flag(task, TIF_SINGLESTEP);
Index: linux-work/arch/powerpc/kernel/head_booke.h
===================================================================
--- linux-work.orig/arch/powerpc/kernel/head_booke.h 2009-05-29 14:24:47.000000000 +1000
+++ linux-work/arch/powerpc/kernel/head_booke.h 2009-05-29 14:54:26.000000000 +1000
@@ -256,7 +256,7 @@ label:
* off DE in the DSRR1 value and clearing the debug status. \
*/ \
mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
- andis. r10,r10,DBSR_IC@h; \
+ andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \
beq+ 2f; \
\
lis r10,KERNELBASE@h; /* check if exception in vectors */ \
@@ -271,7 +271,7 @@ label:
\
/* here it looks like we got an inappropriate debug exception. */ \
1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CDRR1 value */ \
- lis r10,DBSR_IC@h; /* clear the IC event */ \
+ lis r10,(DBSR_IC|DBSR_BT)@h; /* clear the IC event */ \
mtspr SPRN_DBSR,r10; \
/* restore state and get out */ \
lwz r10,_CCR(r11); \
@@ -309,7 +309,7 @@ label:
* off DE in the CSRR1 value and clearing the debug status. \
*/ \
mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
- andis. r10,r10,DBSR_IC@h; \
+ andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \
beq+ 2f; \
\
lis r10,KERNELBASE@h; /* check if exception in vectors */ \
@@ -317,14 +317,14 @@ label:
cmplw r12,r10; \
blt+ 2f; /* addr below exception vectors */ \
\
- lis r10,DebugCrit@h; \
+ lis r10,DebugCrit@h; \
ori r10,r10,DebugCrit@l; \
cmplw r12,r10; \
bgt+ 2f; /* addr above exception vectors */ \
\
/* here it looks like we got an inappropriate debug exception. */ \
1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \
- lis r10,DBSR_IC@h; /* clear the IC event */ \
+ lis r10,(DBSR_IC|DBSR_BT)@h; /* clear the IC event */ \
mtspr SPRN_DBSR,r10; \
/* restore state and get out */ \
lwz r10,_CCR(r11); \
Index: linux-work/arch/powerpc/kernel/traps.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/traps.c 2009-05-29 14:32:06.000000000 +1000
+++ linux-work/arch/powerpc/kernel/traps.c 2009-05-29 17:02:35.000000000 +1000
@@ -1041,7 +1041,34 @@ void SoftwareEmulation(struct pt_regs *r
void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
{
- if (debug_status & DBSR_IC) { /* instruction completion */
+ /* Hack alert: On BookE, Branch Taken stops on the branch itself, while
+ * on server, it stops on the target of the branch. In order to simulate
+ * the server behaviour, we thus restart right away with a single step
+ * instead of stopping here when hitting a BT
+ */
+ if (debug_status & DBSR_BT) {
+ regs->msr &= ~MSR_DE;
+
+ /* Disable BT */
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_BT);
+ /* Clear the BT event */
+ mtspr(SPRN_DBSR, DBSR_BT);
+
+ /* Do the single step trick only when coming from userspace */
+ if (user_mode(regs)) {
+ current->thread.dbcr0 &= ~DBCR0_BT;
+ current->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
+ regs->msr |= MSR_DE;
+ return;
+ }
+
+ if (notify_die(DIE_SSTEP, "block_step", regs, 5,
+ 5, SIGTRAP) == NOTIFY_STOP) {
+ return;
+ }
+ if (debugger_sstep(regs))
+ return;
+ } else if (debug_status & DBSR_IC) { /* Instruction complete */
regs->msr &= ~MSR_DE;
/* Disable instruction completion */
@@ -1057,9 +1084,8 @@ void __kprobes DebugException(struct pt_
if (debugger_sstep(regs))
return;
- if (user_mode(regs)) {
- current->thread.dbcr0 &= ~DBCR0_IC;
- }
+ if (user_mode(regs))
+ current->thread.dbcr0 &= ~(DBCR0_IC);
_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
} else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {
^ permalink raw reply
* Re: [PATCH] powerpc ptrace block-step
From: Roland McGrath @ 2009-05-29 7:32 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, utrace-devel
In-Reply-To: <1243573429.17903.30.camel@pasglop>
Thanks! I'm very glad to finally see this ironed out by someone who
actually knows about powerpc innards.
Thanks,
Roland
^ permalink raw reply
* Re: [PATCH] powerpc ptrace block-step
From: Benjamin Herrenschmidt @ 2009-05-29 7:39 UTC (permalink / raw)
To: Roland McGrath; +Cc: linuxppc-dev, utrace-devel
In-Reply-To: <20090529073213.B7227FC2BD@magilla.sf.frob.com>
On Fri, 2009-05-29 at 00:32 -0700, Roland McGrath wrote:
> Thanks! I'm very glad to finally see this ironed out by someone who
> actually knows about powerpc innards.
yeah, it's been on my todo list for some time... decided that it stayed
rotting for too long. We also did a little test program to exercise wich
is how I discovered the subtle difference between BookE and server.
Any comment about my approach of making BookE "look like" server by
sticking a single step in there ? IE. Is the semantic of stopping on the
-target- of the branch what userspace expects ?
Cheers,
Ben.
^ permalink raw reply
* A few more things in -test
From: Benjamin Herrenschmidt @ 2009-05-29 7:44 UTC (permalink / raw)
To: linuxppc-dev list
I pushed out a few more things in -test. I'll do a new -next with these
and maybe a couple of other things on monday hopefully.
Anton Blanchard (1):
powerpc: Convert RTAS event scan from kernel thread to workqueue
Becky Bruce (1):
powerpc: Add support for swiotlb
Michael Ellerman (3):
powerpc/ftrace: Use ppc_function_entry() instead of GET_ADDR
powerpc/ftrace: Remove unused macros
powerpc/ftrace: Use PPC_INST_NOP directly
Michael Neuling (1):
powerpc: Make the NR_CPUS max 8192
Michel Dänzer (1):
therm_adt746x: Always clear hardware bit which inverts fan speed range.
Nathan Fontenot (1):
powerpc: Display processor virtualization resource allocs in lparcfg
roel kluin (1):
tape: beyond ARRAY_SIZE of viocd_diskinfo
^ permalink raw reply
* Re: [RFC/PATCH] powerpc: Add PTRACE_SINGLEBLOCK support
From: Roland McGrath @ 2009-05-29 7:53 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <20090529072644.7797ADDF84@ozlabs.org>
> The BookE variant is superior in some ways as it allows to know where
> you come from on branches. But that also means that the semantics exposed
> to user space would not be consistent which is BAD (tm).
If it were me I would start with a simpler patch that doesn't implement it
at all on BookE, and arch_has_block_step() yields 0 on those configs.
Later on when someone using BookE asks for it, revisit the complexity.
But that doesn't mean you shouldn't just go with what you've done now.
The reality is that there is no user expectation established one way or
another yet. For a long time only ia64 had PTRACE_SINGLEBLOCK and for not
too many kernel versions has x86 had it too. There aren't yet other
established uses of user_enable_block_step() so as to have an expectation
of what the semantics are.
arch_has_block_step() by itself does not indicate the details. If there
is something more generic that starts to use this and thus cares to know
exactly what "block step" means, then we can figure it out. My first
inclination is to have arch code provide only what is most natural and
simple on the given CPU and just have more-specific arch macros/inlines
saying what the behavior is (before branch or after branch, and whether
also before non-taken branches, are the only two bits of variance I can
think of). Then whatever generic thing is built on this can test those
and cope. i.e., a non-arch layer would be responsible for deciding that
doing an immediate single-step was the useful thing to do for this CPU's
flavor of block-step.
But I don't feel at all strongly that you shouldn't just roll it into
the arch code as you have done. It's up to you--and really it's just
pending this getting exercised for any real-world purpose to see what
one really wants. (Chances are such things would get done on x86 first,
where they might take advantage of several flavors of branch
source/target recording features. So seeing what of all that some
actual tool used in practice might inform one's looking into what
analogues or subsets powerpc chips have to offer.)
Thanks,
Roland
^ permalink raw reply
* [PATCH] powerpc/cpm2: make cpm2_pic the default host
From: Wolfram Sang @ 2009-05-29 8:31 UTC (permalink / raw)
To: w.sang; +Cc: linuxppc-dev
In-Reply-To: <547eba1b0905281746h970028br9685085d18dceb6e@mail.gmail.com>
As stated in the source, this one is usually the only
interrupt-controller. To ease creating virq mappings, let it be the
default host.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Daniel Ng <daniel.ng1234@gmail.com>
Cc: Vitaly Bordug <vitb@kernel.crashing.org>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: linuxppc-dev@ozlabs.org
---
arch/powerpc/sysdev/cpm2_pic.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index 78f1f7c..7a7d4e5 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -272,4 +272,5 @@ void cpm2_pic_init(struct device_node *node)
printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
return;
}
+ irq_set_default_host(cpm2_pic_host);
}
--
1.6.2
^ permalink raw reply related
* (no subject)
From: Ian Campbell @ 2009-05-29 8:43 UTC (permalink / raw)
To: linux-kernel
Cc: x86, Jeremy Fitzhardinge, Tony Luck, linux-ia64, Ian Campbell,
Olaf Kirch, Greg KH, FUJITA Tomonori, linuxppc-dev, Ingo Molnar
This series:
* removes the swiotlb_(arch_)_phys_to_bus and bus_to_phys __weak
hooks, replacing them with an architecture-specific phys_to_dma and
dma_to_phys interface. These are used by both PowerPC and Xen to
provide the correct mapping from physical to DMA addresses.
* removes the swiotlb_address_needs_mapping and
swiotlb_range_needs_mapping __weak functions as well as
is_buffer_dma_capable (which should never have been a generic
function). All three are replaced by a single architecture-specific
interface which meets the needs of both PowerPC and Xen.
* removes the swiotlb_virt_to_bus __weak function and replaces it with
a CONFIG_HIGHMEM compatible version when high memory is in use. This
is needed for 32 bit PowerPC swiotlb support.
I think these new interfaces are cleaner than the existing __weak
functions and isolate the swiotlb code from architecture internals.
This series does not contain any Xen or PowerPC specific changes, those
will follow in separate postings. The complete patchset has been boot
tested under Xen and native-x86 and compiled for IA64 and PowerPC
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Becky Bruce <beckyb@kernel.crashing.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Greg KH <gregkh@suse.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Olaf Kirch <okir@suse.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-ia64@vger.kernel.org
Cc: linuxppc-dev@ozlabs.org
Cc: x86@kernel.org
^ permalink raw reply
* [PATCH 6/9] swiotlb: use dma_to_phys and phys_to_dma
From: Ian Campbell @ 2009-05-29 8:44 UTC (permalink / raw)
To: linux-kernel
Cc: Benjamin, x86, Jeremy Fitzhardinge, Tony Luck, Olaf, Ian Campbell,
Kirch, Greg KH, FUJITA Tomonori, linuxppc-dev, linux-ia64
In-Reply-To: <1243586643-5554-1-git-send-email-ian.campbell@citrix.com>
These new architecture-specific interfaces subsume the existing __weak
function hooks.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Olaf Kirch <okir@suse.de>
Cc: Greg KH <gregkh@suse.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Becky Bruce <beckyb@kernel.crashing.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: x86@kernel.org
Cc: linux-ia64@vger.kernel.org
Cc: linuxppc-dev@ozlabs.org
---
include/linux/swiotlb.h | 5 -----
lib/swiotlb.c | 18 ++++--------------
2 files changed, 4 insertions(+), 19 deletions(-)
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index cb1a663..954feec 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -27,11 +27,6 @@ swiotlb_init(void);
extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
extern void *swiotlb_alloc(unsigned order, unsigned long nslabs);
-extern dma_addr_t swiotlb_phys_to_bus(struct device *hwdev,
- phys_addr_t address);
-extern phys_addr_t swiotlb_bus_to_phys(struct device *hwdev,
- dma_addr_t address);
-
extern int swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size);
extern void
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index bffe6d7..baa1991 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -124,25 +124,15 @@ void * __weak swiotlb_alloc(unsigned order, unsigned long nslabs)
return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order);
}
-dma_addr_t __weak swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
-{
- return paddr;
-}
-
-phys_addr_t __weak swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
-{
- return baddr;
-}
-
static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
volatile void *address)
{
- return swiotlb_phys_to_bus(hwdev, virt_to_phys(address));
+ return phys_to_dma(hwdev, virt_to_phys(address));
}
void * __weak swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
{
- return phys_to_virt(swiotlb_bus_to_phys(hwdev, address));
+ return phys_to_virt(dma_to_phys(hwdev, address));
}
int __weak swiotlb_arch_address_needs_mapping(struct device *hwdev,
@@ -646,7 +636,7 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
struct dma_attrs *attrs)
{
phys_addr_t phys = page_to_phys(page) + offset;
- dma_addr_t dev_addr = swiotlb_phys_to_bus(dev, phys);
+ dma_addr_t dev_addr = phys_to_dma(dev, phys);
void *map;
BUG_ON(dir == DMA_NONE);
@@ -817,7 +807,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
for_each_sg(sgl, sg, nelems, i) {
phys_addr_t paddr = sg_phys(sg);
- dma_addr_t dev_addr = swiotlb_phys_to_bus(hwdev, paddr);
+ dma_addr_t dev_addr = phys_to_dma(hwdev, paddr);
if (range_needs_mapping(paddr, sg->length) ||
address_needs_mapping(hwdev, dev_addr, sg->length)) {
--
1.5.6.5
^ permalink raw reply related
* [PATCH 8/9] swiotlb: support HIGHMEM in swiotlb_bus_to_virt
From: Ian Campbell @ 2009-05-29 8:44 UTC (permalink / raw)
To: linux-kernel
Cc: Fitzhardinge, Jeremy, Ian Campbell, Tomonori, linuxppc-dev,
Ingo Molnar, FUJITA
In-Reply-To: <1243586643-5554-1-git-send-email-ian.campbell@citrix.com>
Rather than supplying a __weak hook which architectures which support
highmem can overide simply provide a version of swiotlb_bus_to_virt
which works with high memory. Make it conditional since it is a more
expensive variant than the non-highmem version.
Acutal function contents taken from the PowerPC swiotlb patchset by
Becky Bruce.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Becky Bruce <beckyb@kernel.crashing.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: linuxppc-dev@ozlabs.org
---
lib/swiotlb.c | 14 +++++++++++++-
1 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index e332342..c50a5ed 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -130,10 +130,22 @@ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
return phys_to_dma(hwdev, virt_to_phys(address));
}
-void * __weak swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
+#ifdef CONFIG_HIGHMEM
+static void * swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
+{
+ unsigned long pfn = PFN_DOWN(dma_to_phys(hwdev, addr));
+ void *pageaddr = page_address(pfn_to_page(pfn));
+
+ if (pageaddr != NULL)
+ return pageaddr + (addr % PAGE_SIZE);
+ return NULL;
+}
+#else
+static void * swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
{
return phys_to_virt(dma_to_phys(hwdev, address));
}
+#endif
static void swiotlb_print_info(unsigned long bytes)
{
--
1.5.6.5
^ permalink raw reply related
* [PATCH 7/9] swiotlb: use dma_map_range
From: Ian Campbell @ 2009-05-29 8:44 UTC (permalink / raw)
To: linux-kernel
Cc: Benjamin, x86, Jeremy Fitzhardinge, Tony Luck, Olaf, Ian Campbell,
Kirch, Greg KH, FUJITA Tomonori, linuxppc-dev, linux-ia64
In-Reply-To: <1243586643-5554-1-git-send-email-ian.campbell@citrix.com>
This replaces usages of address_needs_mapping, range_needs_mapping and
is_buffer_dma_capable and the __weak architecture hooks to those
functions with a more flexible single function.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Olaf Kirch <okir@suse.de>
Cc: Greg KH <gregkh@suse.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Becky Bruce <beckyb@kernel.crashing.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: x86@kernel.org
Cc: linux-ia64@vger.kernel.org
Cc: linuxppc-dev@ozlabs.org
---
include/linux/dma-mapping.h | 5 ----
lib/swiotlb.c | 57 +++++++++++++------------------------------
2 files changed, 17 insertions(+), 45 deletions(-)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 8083b6a..85dafa1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -96,11 +96,6 @@ static inline int is_device_dma_capable(struct device *dev)
return dev->dma_mask != NULL && *dev->dma_mask != DMA_MASK_NONE;
}
-static inline int is_buffer_dma_capable(u64 mask, dma_addr_t addr, size_t size)
-{
- return addr + size <= mask;
-}
-
#ifdef CONFIG_HAS_DMA
#include <asm/dma-mapping.h>
#else
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index baa1991..e332342 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -135,17 +135,6 @@ void * __weak swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
return phys_to_virt(dma_to_phys(hwdev, address));
}
-int __weak swiotlb_arch_address_needs_mapping(struct device *hwdev,
- dma_addr_t addr, size_t size)
-{
- return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
-}
-
-int __weak swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size)
-{
- return 0;
-}
-
static void swiotlb_print_info(unsigned long bytes)
{
phys_addr_t pstart, pend;
@@ -305,17 +294,6 @@ cleanup1:
return -ENOMEM;
}
-static inline int
-address_needs_mapping(struct device *hwdev, dma_addr_t addr, size_t size)
-{
- return swiotlb_arch_address_needs_mapping(hwdev, addr, size);
-}
-
-static inline int range_needs_mapping(phys_addr_t paddr, size_t size)
-{
- return swiotlb_force || swiotlb_arch_range_needs_mapping(paddr, size);
-}
-
static int is_swiotlb_buffer(char *addr)
{
return addr >= io_tlb_start && addr < io_tlb_end;
@@ -542,7 +520,7 @@ void *
swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags)
{
- dma_addr_t dev_addr;
+ phys_addr_t phys;
void *ret;
int order = get_order(size);
u64 dma_mask = DMA_BIT_MASK(32);
@@ -551,9 +529,8 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_mask = hwdev->coherent_dma_mask;
ret = (void *)__get_free_pages(flags, order);
- if (ret &&
- !is_buffer_dma_capable(dma_mask, swiotlb_virt_to_bus(hwdev, ret),
- size)) {
+ if (ret && !dma_map_range(hwdev, dma_mask, virt_to_phys(ret),
+ size, dma_handle)) {
/*
* The allocated memory isn't reachable by the device.
*/
@@ -572,19 +549,18 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
}
memset(ret, 0, size);
- dev_addr = swiotlb_virt_to_bus(hwdev, ret);
+ phys = virt_to_phys(ret);
/* Confirm address can be DMA'd by device */
- if (!is_buffer_dma_capable(dma_mask, dev_addr, size)) {
- printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
+ if (!dma_map_range(hwdev, dma_mask, phys, size, dma_handle)) {
+ printk("hwdev DMA mask = 0x%016Lx, physical addr = 0x%016Lx\n",
(unsigned long long)dma_mask,
- (unsigned long long)dev_addr);
+ (unsigned long long)phys);
/* DMA_TO_DEVICE to avoid memcpy in unmap_single */
do_unmap_single(hwdev, ret, size, DMA_TO_DEVICE);
return NULL;
}
- *dma_handle = dev_addr;
return ret;
}
EXPORT_SYMBOL(swiotlb_alloc_coherent);
@@ -636,7 +612,7 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
struct dma_attrs *attrs)
{
phys_addr_t phys = page_to_phys(page) + offset;
- dma_addr_t dev_addr = phys_to_dma(dev, phys);
+ dma_addr_t dev_addr;
void *map;
BUG_ON(dir == DMA_NONE);
@@ -645,8 +621,8 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
* we can safely return the device addr and not worry about bounce
* buffering it.
*/
- if (!address_needs_mapping(dev, dev_addr, size) &&
- !range_needs_mapping(phys, size))
+ if (dma_map_range(dev, dma_get_mask(dev), phys, size, &dev_addr) &&
+ !swiotlb_force)
return dev_addr;
/*
@@ -658,12 +634,12 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
map = io_tlb_overflow_buffer;
}
- dev_addr = swiotlb_virt_to_bus(dev, map);
+ phys = virt_to_phys(map);
/*
* Ensure that the address returned is DMA'ble
*/
- if (address_needs_mapping(dev, dev_addr, size))
+ if (!dma_map_range(dev, dma_get_mask(dev), phys, size, &dev_addr))
panic("map_single: bounce buffer is not DMA'ble");
return dev_addr;
@@ -807,10 +783,10 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
for_each_sg(sgl, sg, nelems, i) {
phys_addr_t paddr = sg_phys(sg);
- dma_addr_t dev_addr = phys_to_dma(hwdev, paddr);
+ dma_addr_t uninitialized_var(dev_addr);
- if (range_needs_mapping(paddr, sg->length) ||
- address_needs_mapping(hwdev, dev_addr, sg->length)) {
+ if (!dma_map_range(hwdev, dma_get_mask(hwdev), dev_addr, sg->length, &dev_addr) ||
+ swiotlb_force) {
void *map = map_single(hwdev, sg_phys(sg),
sg->length, dir);
if (!map) {
@@ -822,7 +798,8 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
sgl[0].dma_length = 0;
return 0;
}
- sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
+ paddr = virt_to_phys(map);
+ sg->dma_address = phys_to_dma(hwdev, paddr);
} else
sg->dma_address = dev_addr;
sg->dma_length = sg->length;
--
1.5.6.5
^ permalink raw reply related
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