* Re: 8544 external interrupt configuration problems
From: Scott Wood @ 2009-05-29 17:09 UTC (permalink / raw)
To: Nancy Isaac; +Cc: linuxppc-dev
In-Reply-To: <1bcc666d0905281848m5d237742h12b4bac272f28ca9@mail.gmail.com>
On Thu, May 28, 2009 at 06:48:48PM -0700, Nancy Isaac wrote:
> > Is the level/sense information correct?
>
>
> [NI] Yes, these interrupts are supposed to be active low, level sensitive
> interrupts.
But the level/sense value for that on mpic is 1, not 2. 2 is active
high (see Documentation/powerpc/booting-without-of.txt).
-Scott
^ permalink raw reply
* Re: [PATCH 8/9] swiotlb: support HIGHMEM in swiotlb_bus_to_virt
From: Jeremy Fitzhardinge @ 2009-05-29 15:58 UTC (permalink / raw)
To: Ian Campbell; +Cc: linux-kernel, FUJITA Tomonori, linuxppc-dev, Ingo Molnar
In-Reply-To: <1243586643-5554-9-git-send-email-ian.campbell@citrix.com>
Ian Campbell wrote:
> 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)
>
I think it would be better to put the #ifdef within the function body so
that there's no chance of prototype-drift.
> +{
> + 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);
>
Is there an arch-independent test to see if a pfn is considered highmem
or not (which returns a constant on non-highmem configurations)? If so,
then I think this could be common without having to go via a struct page.
J
^ permalink raw reply
* Re: [Patch 2/6] Introduce PPC64 specific Hardware Breakpoint interfaces
From: K.Prasad @ 2009-05-29 13:54 UTC (permalink / raw)
To: David Gibson
Cc: Michael Neuling, Benjamin Herrenschmidt, linuxppc-dev, Alan Stern,
paulus, Roland McGrath
In-Reply-To: <20090529041849.GD8621@yookeroo.seuss>
On Fri, May 29, 2009 at 02:18:49PM +1000, David Gibson wrote:
> On Mon, May 25, 2009 at 06:45:22AM +0530, K.Prasad wrote:
> > +/*
> > + * 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.
>
Yes, I see that the comment
" * @triggered: callback invoked after target address access"
in include/asm-generic/hw_breakpoint.h which has to be changed. I will
do the same in a follow-on patch to the generic interface after its
integration.
> > +
> > + 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...
>
The put_cpu() usage in hw_breakpoint_handler() and
single_step_dabr_instruction() is actually wrapped with comments.
Do you want a comment about the usage of the per_cpu data variable used
above, or a more descriptive comment in places where put_cpu() is use?
> > +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.
>
Thanks, I realise that this changes the user-space behaviour.
The one-shot hardware breakpoint exception behaviour and also
single-stepping the instruction have changed.
I will modify the hw_breakpoint_handler() to overcome this problem.
Thanks,
K.Prasad
^ permalink raw reply
* fastboot.
From: Kenneth Johansson @ 2009-05-29 11:13 UTC (permalink / raw)
To: linuxppc-dev
http://www.cambridgewireless.co.uk/news/article/default.aspx?objid=36792
Anybody know what they mean by booting here.
I have started the ads5121 board using u-boot and kernel in NOR flash
and root file system on a compact flash card connected to the IDE
interface in 2.05 second until init is started from the rootfs.
This was fast enough for what was needed I did not try to optimize
further but since I already was in the domain where changes impacted
only a few milliseconds I have a hard time imagining going down to less
than a second.
So I guess the only way is to skip u-boot and run linux kernel directly
out of NOR. Anyone know what MontaVista is doing ??
^ permalink raw reply
* Re: MPC8272- Porting HDLC driver from 2.6.14 to 2.6.27- "no_irq_chip" error
From: Frank Svendsbøe @ 2009-05-29 10:56 UTC (permalink / raw)
To: Wolfram Sang; +Cc: linuxppc-dev@ozlabs.org, Daniel Ng, Norbert van Bolhuis
In-Reply-To: <20090528123311.GA3112@pengutronix.de>
FYI. The same applies to mpc8xx targets: No default host interrupt controll=
er.
The following patch was needed for our target:
---
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_=
pic.c
index 5d2d552..92b2b66 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -186,6 +186,7 @@ int mpc8xx_pic_init(void)
ret =3D -ENOMEM;
goto out;
}
+ irq_set_default_host(mpc8xx_pic_host);
return 0;
out:
---
Maybe setting a default host ought to be mandatory? Or is doing the
mapping manually
(without device tree descriptions) considered being a hack?
Frank
On Thu, May 28, 2009 at 2:33 PM, Wolfram Sang <w.sang@pengutronix.de> wrote=
:
>> this is an example of how a simple 8313 Periodic Interval Timer (PIT) ke=
rnel driver
>> registers for the PIT IRQ (Interrupt ID 65)
>>
>> #define PIT_IRQ 65
>>
>> =A0 =A0 virq =3D irq_create_mapping(NULL, PIT_IRQ);
>> =A0 =A0 set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
>>
>> =A0 =A0 if(request_irq(virq, (irq_handler_t)timerEvent, 0, "timer2", (vo=
id *)0)) {
>> =A0 =A0 =A0 =A0 printk(KERN_ERR "request_irq() returned error for irq=3D=
%d virq=3D%d\n", PIT_IRQ, virq);
>> =A0 =A0 }
>
> 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?
>
> =3D=3D=3D
>
> 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>
> ---
> =A0arch/powerpc/sysdev/cpm2_pic.c | =A0 =A01 +
> =A01 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pi=
c.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)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0printk(KERN_ERR "CPM2 PIC: failed to alloc=
ate irq host!\n");
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return;
> =A0 =A0 =A0 =A0}
> + =A0 =A0 =A0 irq_set_default_host(cpm2_pic_host);
> =A0}
>
> --
> Pengutronix e.K. =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 | Wo=
lfram Sang =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0|
> Industrial Linux Solutions =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 | http://www.p=
engutronix.de/ =A0|
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAkoehIYACgkQD27XaX1/VRsAygCePysW72eSPbW0rdM5DZ6lJS+7
> lEwAoItsU+K2CO9Eqfrwj64TgwEskB85
> =3D+3mh
> -----END PGP SIGNATURE-----
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
^ permalink raw reply related
* Re: [Patch 1/6] Prepare the PowerPC platform for HW Breakpoint infrastructure
From: K.Prasad @ 2009-05-29 9:53 UTC (permalink / raw)
To: linuxppc-dev, David Gibson
Cc: paulus, Michael Neuling, Benjamin Herrenschmidt, Alan Stern,
Roland McGrath
In-Reply-To: <20090529032048.GB8621@yookeroo.seuss>
On Fri, May 29, 2009 at 01:20:48PM +1000, David Gibson wrote:
> 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.
>
Okay.
> > +};
> > +
> > +#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.
>
As I said before, the signatures of some of these functions are
different. But I agree that we may want to eventually consolidate them
into the generic header file, during future enhancements.
Thanks,
K.Prasad
> --
> 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: swiotlb: Introduce architecture-specific APIs to replace __weak functions
From: Ian Campbell @ 2009-05-29 9:06 UTC (permalink / raw)
To: linux-kernel@vger.kernel.org
Cc: x86@kernel.org, Jeremy Fitzhardinge, Tony Luck,
linux-ia64@vger.kernel.org, Olaf Kirch, Greg KH, FUJITA Tomonori,
linuxppc-dev@ozlabs.org, Ingo Molnar
In-Reply-To: <1243586643-5554-1-git-send-email-ian.campbell@citrix.com>
[-- Attachment #1: Type: text/plain, Size: 11060 bytes --]
Subject should have been "swiotlb: Introduce architecture-specific APIs
to replace __weak functions". Seems I never drive git send-email right
first time...
On Fri, 2009-05-29 at 04:43 -0400, Ian Campbell wrote:
> This series does not contain any Xen or PowerPC specific changes, those
> will follow in separate postings.
Becky, here is an updated version of your 2/3 "powerpc: Add support for
swiotlb on 32-bit" [0], compile tested with the new interfaces. The
interdiff is attached.
Ian.
[0] http://ozlabs.org/pipermail/linuxppc-dev/2009-May/072140.html
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index cdc9a6f..561abf9 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -296,9 +296,19 @@ config IOMMU_VMERGE
config IOMMU_HELPER
def_bool PPC64
+config SWIOTLB
+ bool "SWIOTLB support"
+ default n
+ select IOMMU_HELPER
+ ---help---
+ Support for IO bounce buffering for systems without an IOMMU.
+ This allows us to DMA to the full physical address space on
+ platforms where the size of a physical address is larger
+ than the bus address. Not all platforms support this.
+
config PPC_NEED_DMA_SYNC_OPS
def_bool y
- depends on NOT_COHERENT_CACHE
+ depends on (NOT_COHERENT_CACHE || SWIOTLB)
config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index cb448d6..b2fcd2b 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -15,9 +15,18 @@
#include <linux/scatterlist.h>
#include <linux/dma-attrs.h>
#include <asm/io.h>
+#include <asm/swiotlb.h>
#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
+/* Some dma direct funcs must be visible for use in other dma_ops */
+extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag);
+extern void dma_direct_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle);
+
+extern unsigned long get_dma_direct_offset(struct device *dev);
+
#ifdef CONFIG_NOT_COHERENT_CACHE
/*
* DMA-consistent mapping functions for PowerPCs that don't support
@@ -78,6 +87,9 @@ struct dma_mapping_ops {
dma_addr_t dma_address, size_t size,
enum dma_data_direction direction,
struct dma_attrs *attrs);
+ bool (*map_range)(struct device *dev, u64 mask,
+ phys_addr_t addr, size_t size,
+ dma_addr_t *dma_addr_p);
#ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
void (*sync_single_range_for_cpu)(struct device *hwdev,
dma_addr_t dma_handle, unsigned long offset,
@@ -290,6 +302,16 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
dma_unmap_sg_attrs(dev, sg, nhwentries, direction, NULL);
}
+static inline bool dma_map_range(struct device *hwdev, u64 mask,
+ phys_addr_t addr, size_t size,
+ dma_addr_t *dma_addr_p)
+{
+ struct dma_mapping_ops *dma_ops = get_dma_ops(hwdev);
+
+ BUG_ON(!dma_ops);
+ return dma_ops->map_range(hwdev, mask, addr, size, dma_addr_p);
+}
+
#ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
static inline void dma_sync_single_for_cpu(struct device *dev,
dma_addr_t dma_handle, size_t size,
@@ -409,6 +431,16 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
#define dma_is_consistent(d, h) (1)
#endif
+static inline dma_addr_t phys_to_dma(struct device *hwdev, phys_addr_t paddr)
+{
+ return paddr + get_dma_direct_offset(hwdev);
+}
+
+static inline phys_addr_t dma_to_phys(struct device *hwdev, dma_addr_t daddr)
+{
+ return daddr + get_dma_direct_offset(hwdev);
+}
+
static inline int dma_get_cache_alignment(void)
{
#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
new file mode 100644
index 0000000..30891d6
--- /dev/null
+++ b/arch/powerpc/include/asm/swiotlb.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2009 Becky Bruce, Freescale Semiconductor
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ASM_SWIOTLB_H
+#define __ASM_SWIOTLB_H
+
+#include <linux/swiotlb.h>
+
+extern struct dma_mapping_ops swiotlb_dma_ops;
+extern struct dma_mapping_ops swiotlb_pci_dma_ops;
+
+int swiotlb_arch_address_needs_mapping(struct device *, dma_addr_t,
+ size_t size);
+
+static inline void dma_mark_clean(void *addr, size_t size) {}
+
+extern unsigned int ppc_swiotlb_enable;
+int __init swiotlb_setup_bus_notifier(void);
+
+#endif /* __ASM_SWIOTLB_H */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 9ba1bb7..f6d720b 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
+obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
pci64-$(CONFIG_PPC64) += pci_dn.o isa-bridge.o
obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
new file mode 100644
index 0000000..ef2e812
--- /dev/null
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -0,0 +1,137 @@
+/*
+ * Contains routines needed to support swiotlb for ppc.
+ *
+ * Copyright (C) 2009 Becky Bruce, Freescale Semiconductor
+ *
+ * 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.
+ *
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/pfn.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+
+#include <asm/machdep.h>
+#include <asm/swiotlb.h>
+#include <asm/dma.h>
+#include <asm/abs_addr.h>
+
+int swiotlb __read_mostly;
+unsigned int ppc_swiotlb_enable;
+
+/*
+ * Determine if an address is reachable by a pci device, or if we must bounce.
+ */
+static bool
+pci_map_range(struct device *hwdev, u64 mask,
+ phys_addr_t addr, size_t size,
+ dma_addr_t *dma_addr_p)
+{
+ dma_addr_t dma_addr = phys_to_dma(hwdev, addr);
+ dma_addr_t max;
+ struct pci_controller *hose;
+ struct pci_dev *pdev = to_pci_dev(hwdev);
+
+ hose = pci_bus_to_host(pdev->bus);
+ max = hose->dma_window_base_cur + hose->dma_window_size;
+
+ /* check that we're within mapped pci window space */
+ if ((dma_addr + size > max) | (dma_addr < hose->dma_window_base_cur))
+ return false;
+
+ *dma_addr_p = dma_addr;
+ return true;
+}
+
+static bool
+map_range(struct device *dev, u64 mask,
+ phys_addr_t addr, size_t size,
+ dma_addr_t *dma_addr_p)
+{
+ dma_addr_t dma_addr = phys_to_dma(dev, addr);
+
+ if (dma_addr + size > mask)
+ return false;
+
+ *dma_addr_p = dma_addr;
+ return true;
+}
+
+
+/*
+ *@the moment, all platforms that use this code only require
+ * swiotlb to be used if we're operating on HIGHMEM. Since
+ * we don't ever call anything other than map_sg, unmap_sg,
+ * map_page, and unmap_page on highmem, use normal dma_ops
+ * for everything else.
+ */
+struct dma_mapping_ops swiotlb_dma_ops = {
+ .alloc_coherent = dma_direct_alloc_coherent,
+ .free_coherent = dma_direct_free_coherent,
+ .map_sg = swiotlb_map_sg_attrs,
+ .unmap_sg = swiotlb_unmap_sg_attrs,
+ .dma_supported = swiotlb_dma_supported,
+ .map_page = swiotlb_map_page,
+ .unmap_page = swiotlb_unmap_page,
+ .map_range = map_range,
+ .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
+ .sync_single_range_for_device = swiotlb_sync_single_range_for_device,
+ .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+ .sync_sg_for_device = swiotlb_sync_sg_for_device
+};
+
+struct dma_mapping_ops swiotlb_pci_dma_ops = {
+ .alloc_coherent = dma_direct_alloc_coherent,
+ .free_coherent = dma_direct_free_coherent,
+ .map_sg = swiotlb_map_sg_attrs,
+ .unmap_sg = swiotlb_unmap_sg_attrs,
+ .dma_supported = swiotlb_dma_supported,
+ .map_page = swiotlb_map_page,
+ .unmap_page = swiotlb_unmap_page,
+ .map_range = pci_map_range,
+ .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
+ .sync_single_range_for_device = swiotlb_sync_single_range_for_device,
+ .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+ .sync_sg_for_device = swiotlb_sync_sg_for_device
+};
+
+static int ppc_swiotlb_bus_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct device *dev = data;
+
+ /* We are only intereted in device addition */
+ if (action != BUS_NOTIFY_ADD_DEVICE)
+ return 0;
+
+ /* May need to bounce if the device can't address all of DRAM */
+ if (dma_get_mask(dev) < lmb_end_of_DRAM())
+ set_dma_ops(dev, &swiotlb_dma_ops);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ppc_swiotlb_plat_bus_notifier = {
+ .notifier_call = ppc_swiotlb_bus_notify,
+ .priority = 0,
+};
+
+static struct notifier_block ppc_swiotlb_of_bus_notifier = {
+ .notifier_call = ppc_swiotlb_bus_notify,
+ .priority = 0,
+};
+
+int __init swiotlb_setup_bus_notifier(void)
+{
+ bus_register_notifier(&platform_bus_type,
+ &ppc_swiotlb_plat_bus_notifier);
+ bus_register_notifier(&of_platform_bus_type,
+ &ppc_swiotlb_of_bus_notifier);
+
+ return 0;
+}
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 6b02793..20a60d6 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -19,7 +19,7 @@
* default the offset is PCI_DRAM_OFFSET.
*/
-static unsigned long get_dma_direct_offset(struct device *dev)
+unsigned long get_dma_direct_offset(struct device *dev)
{
if (dev)
return (unsigned long)dev->archdata.dma_data;
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 9e1ca74..1d15424 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -39,6 +39,7 @@
#include <asm/serial.h>
#include <asm/udbg.h>
#include <asm/mmu_context.h>
+#include <asm/swiotlb.h>
#include "setup.h"
@@ -332,6 +333,11 @@ void __init setup_arch(char **cmdline_p)
ppc_md.setup_arch();
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
+#ifdef CONFIG_SWIOTLB
+ if (ppc_swiotlb_enable)
+ swiotlb_init();
+#endif
+
paging_init();
/* Initialize the MMU context management stuff */
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index c410c60..fbcca72 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -61,6 +61,7 @@
#include <asm/xmon.h>
#include <asm/udbg.h>
#include <asm/kexec.h>
+#include <asm/swiotlb.h>
#include "setup.h"
@@ -524,6 +525,11 @@ void __init setup_arch(char **cmdline_p)
if (ppc_md.setup_arch)
ppc_md.setup_arch();
+#ifdef CONFIG_SWIOTLB
+ if (ppc_swiotlb_enable)
+ swiotlb_init();
+#endif
+
paging_init();
ppc64_boot_msg(0x15, "Setup Done");
}
[-- Attachment #2: interdiff --]
[-- Type: text/x-patch, Size: 5368 bytes --]
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 3d9e887..b2fcd2b 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -87,8 +87,9 @@ struct dma_mapping_ops {
dma_addr_t dma_address, size_t size,
enum dma_data_direction direction,
struct dma_attrs *attrs);
- int (*addr_needs_map)(struct device *dev, dma_addr_t addr,
- size_t size);
+ bool (*map_range)(struct device *dev, u64 mask,
+ phys_addr_t addr, size_t size,
+ dma_addr_t *dma_addr_p);
#ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
void (*sync_single_range_for_cpu)(struct device *hwdev,
dma_addr_t dma_handle, unsigned long offset,
@@ -301,6 +302,16 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
dma_unmap_sg_attrs(dev, sg, nhwentries, direction, NULL);
}
+static inline bool dma_map_range(struct device *hwdev, u64 mask,
+ phys_addr_t addr, size_t size,
+ dma_addr_t *dma_addr_p)
+{
+ struct dma_mapping_ops *dma_ops = get_dma_ops(hwdev);
+
+ BUG_ON(!dma_ops);
+ return dma_ops->map_range(hwdev, mask, addr, size, dma_addr_p);
+}
+
#ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
static inline void dma_sync_single_for_cpu(struct device *dev,
dma_addr_t dma_handle, size_t size,
@@ -420,6 +431,16 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
#define dma_is_consistent(d, h) (1)
#endif
+static inline dma_addr_t phys_to_dma(struct device *hwdev, phys_addr_t paddr)
+{
+ return paddr + get_dma_direct_offset(hwdev);
+}
+
+static inline phys_addr_t dma_to_phys(struct device *hwdev, dma_addr_t daddr)
+{
+ return daddr + get_dma_direct_offset(hwdev);
+}
+
static inline int dma_get_cache_alignment(void)
{
#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
index 6c00667..ef2e812 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -24,50 +24,15 @@
int swiotlb __read_mostly;
unsigned int ppc_swiotlb_enable;
-void *swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t addr)
-{
- unsigned long pfn = PFN_DOWN(swiotlb_bus_to_phys(hwdev, addr));
- void *pageaddr = page_address(pfn_to_page(pfn));
-
- if (pageaddr != NULL)
- return pageaddr + (addr % PAGE_SIZE);
- return NULL;
-}
-
-dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
-{
- return paddr + get_dma_direct_offset(hwdev);
-}
-
-phys_addr_t swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
-
-{
- return baddr - get_dma_direct_offset(hwdev);
-}
-
-/*
- * Determine if an address needs bounce buffering via swiotlb.
- * Going forward I expect the swiotlb code to generalize on using
- * a dma_ops->addr_needs_map, and this function will move from here to the
- * generic swiotlb code.
- */
-int
-swiotlb_arch_address_needs_mapping(struct device *hwdev, dma_addr_t addr,
- size_t size)
-{
- struct dma_mapping_ops *dma_ops = get_dma_ops(hwdev);
-
- BUG_ON(!dma_ops);
- return dma_ops->addr_needs_map(hwdev, addr, size);
-}
-
/*
* Determine if an address is reachable by a pci device, or if we must bounce.
*/
-static int
-swiotlb_pci_addr_needs_map(struct device *hwdev, dma_addr_t addr, size_t size)
+static bool
+pci_map_range(struct device *hwdev, u64 mask,
+ phys_addr_t addr, size_t size,
+ dma_addr_t *dma_addr_p)
{
- u64 mask = dma_get_mask(hwdev);
+ dma_addr_t dma_addr = phys_to_dma(hwdev, addr);
dma_addr_t max;
struct pci_controller *hose;
struct pci_dev *pdev = to_pci_dev(hwdev);
@@ -76,16 +41,25 @@ swiotlb_pci_addr_needs_map(struct device *hwdev, dma_addr_t addr, size_t size)
max = hose->dma_window_base_cur + hose->dma_window_size;
/* check that we're within mapped pci window space */
- if ((addr + size > max) | (addr < hose->dma_window_base_cur))
- return 1;
+ if ((dma_addr + size > max) | (dma_addr < hose->dma_window_base_cur))
+ return false;
- return !is_buffer_dma_capable(mask, addr, size);
+ *dma_addr_p = dma_addr;
+ return true;
}
-static int
-swiotlb_addr_needs_map(struct device *hwdev, dma_addr_t addr, size_t size)
+static bool
+map_range(struct device *dev, u64 mask,
+ phys_addr_t addr, size_t size,
+ dma_addr_t *dma_addr_p)
{
- return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
+ dma_addr_t dma_addr = phys_to_dma(dev, addr);
+
+ if (dma_addr + size > mask)
+ return false;
+
+ *dma_addr_p = dma_addr;
+ return true;
}
@@ -104,7 +78,7 @@ struct dma_mapping_ops swiotlb_dma_ops = {
.dma_supported = swiotlb_dma_supported,
.map_page = swiotlb_map_page,
.unmap_page = swiotlb_unmap_page,
- .addr_needs_map = swiotlb_addr_needs_map,
+ .map_range = map_range,
.sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
.sync_single_range_for_device = swiotlb_sync_single_range_for_device,
.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
@@ -119,7 +93,7 @@ struct dma_mapping_ops swiotlb_pci_dma_ops = {
.dma_supported = swiotlb_dma_supported,
.map_page = swiotlb_map_page,
.unmap_page = swiotlb_unmap_page,
- .addr_needs_map = swiotlb_pci_addr_needs_map,
+ .map_range = pci_map_range,
.sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
.sync_single_range_for_device = swiotlb_sync_single_range_for_device,
.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
^ permalink raw reply related
* Re: [RFC/PATCH] powerpc: Add PTRACE_SINGLEBLOCK support
From: Benjamin Herrenschmidt @ 2009-05-29 9:03 UTC (permalink / raw)
To: Roland McGrath; +Cc: linuxppc-dev
In-Reply-To: <20090529075354.853FBFC2BD@magilla.sf.frob.com>
On Fri, 2009-05-29 at 00:53 -0700, Roland McGrath wrote:
> > 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.
Well, the trick to do an additional single step on BookE to mimmic
server is about 3 lines of code :-) And it seems to work just fine, we
wrote a small test app that forks and the parent blocksteps the children
which does a few useless things we put in there, we get the same results
on server and 440.
So I wouldn't bother -removing- it
> 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.
Allright, but it would suck for it to have different semantics on
powerpc depending on the processor you're on. So I think we need
to settle on one semantic for powerpc, and if we want to make the
BookE special one available to userspace, we can do so via a
different call.
> 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.
I agree to some extent but I dislike if the call behaves differently
within a single arch. Don't you agree ?
For example, BookE doesn't have a DABR for data breakpoint, it has
another facility (DACs). However, we do "emulate" the DABR using one
of the DACs to provide that consistency.
Now we do have WIP patches to add more advanced BookE features (direct
access to the DACs, IACs and DVCs (data compare on watchpoints) etc...)
and so at some point we'll provide those more advanced APIs, I suppose
we can roll the BookE "specific" variant of blockstep in there too,
and keep the base API provide server-like semantics that are identical
on BookE and server.
> 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.)
Ok. I think I'll go with that patch then for now. I'll also look at the
WIP stuff for advanced BookE support and see if we can fold the BookE
variant of blockstep in there too for userspace that cares about it.
Cheers,
Ben.
>
> Thanks,
> Roland
^ permalink raw reply
* [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
* [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 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
* (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] 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
* 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
* 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: [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
* 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
* [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: [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] 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: [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
* [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
* [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 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
* 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
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