* [PATCH v3] [POWERPC] devres: Add devm_ioremap_prot()
From: Kumar Gala @ 2008-05-01 3:40 UTC (permalink / raw)
To: linuxppc-dev
Cc: Andrew Morton, Stephen Rothwell, htejun, Jeff Garzik, Greg KH,
linux-kernel, Emilian.Medve
From: Emil Medve <Emilian.Medve@Freescale.com>
We provide an ioremap_flags so provide a corresponding devm_ioremap_prot.
The slight name difference is at Ben Herrenschmidt request as he plans
on changing ioremap_flags to ioremap_prot in the future.
Signed-off-by: Emil Medve <Emilian.Medve@Freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Acked-by: Tejun Heo <htejun@gmail.com>
---
Added license & copyright to devres.c since its new. Hopefully the last
version of this.
- k
arch/powerpc/lib/Makefile | 1 +
arch/powerpc/lib/devres.c | 42 ++++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/io.h | 8 +++++++-
include/linux/io.h | 1 +
lib/devres.c | 2 +-
5 files changed, 52 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/lib/devres.c
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 4bb023f..f1d2cdc 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_SMP) += locks.o
endif
obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o
+obj-$(CONFIG_HAS_IOMEM) += devres.o
diff --git a/arch/powerpc/lib/devres.c b/arch/powerpc/lib/devres.c
new file mode 100644
index 0000000..292115d
--- /dev/null
+++ b/arch/powerpc/lib/devres.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 Freescale Semiconductor, Inc.
+ *
+ * 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/device.h> /* devres_*(), devm_ioremap_release() */
+#include <linux/io.h> /* ioremap_flags() */
+#include <linux/module.h> /* EXPORT_SYMBOL() */
+
+/**
+ * devm_ioremap_prot - Managed ioremap_flags()
+ * @dev: Generic device to remap IO address for
+ * @offset: BUS offset to map
+ * @size: Size of map
+ * @flags: Page flags
+ *
+ * Managed ioremap_prot(). Map is automatically unmapped on driver
+ * detach.
+ */
+void __iomem *devm_ioremap_prot(struct device *dev, resource_size_t offset,
+ size_t size, unsigned long flags)
+{
+ void __iomem **ptr, *addr;
+
+ ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return NULL;
+
+ addr = ioremap_flags(offset, size, flags);
+ if (addr) {
+ *ptr = addr;
+ devres_add(dev, ptr);
+ } else
+ devres_free(ptr);
+
+ return addr;
+}
+EXPORT_SYMBOL(devm_ioremap_prot);
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index afae069..e0062d7 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -2,7 +2,7 @@
#define _ASM_POWERPC_IO_H
#ifdef __KERNEL__
-/*
+/*
* 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
@@ -18,6 +18,9 @@ extern int check_legacy_ioport(unsigned long base_port);
#define _PNPWRP 0xa79
#define PNPBIOS_BASE 0xf000
+#include <linux/device.h>
+#include <linux/io.h>
+
#include <linux/compiler.h>
#include <asm/page.h>
#include <asm/byteorder.h>
@@ -744,6 +747,9 @@ static inline void * bus_to_virt(unsigned long address)
#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
+void __iomem *devm_ioremap_prot(struct device *dev, resource_size_t offset,
+ size_t size, unsigned long flags);
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_IO_H */
diff --git a/include/linux/io.h b/include/linux/io.h
index 831f57c..7a390cf 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -58,6 +58,7 @@ static inline void devm_ioport_unmap(struct device *dev, void __iomem *addr)
}
#endif
+void devm_ioremap_release(struct device *dev, void *res);
void __iomem * devm_ioremap(struct device *dev, resource_size_t offset,
unsigned long size);
void __iomem * devm_ioremap_nocache(struct device *dev, resource_size_t offset,
diff --git a/lib/devres.c b/lib/devres.c
index 26c87c4..72c8909 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -2,7 +2,7 @@
#include <linux/io.h>
#include <linux/module.h>
-static void devm_ioremap_release(struct device *dev, void *res)
+void devm_ioremap_release(struct device *dev, void *res)
{
iounmap(*(void __iomem **)res);
}
--
1.5.4.1
^ permalink raw reply related
* Re: [PATCH] [POWERPC] 86xx: mpc8610_hpcd: add support for PCI Express x8 slot
From: Kumar Gala @ 2008-05-01 3:58 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
In-Reply-To: <20080429164112.GA11425@polina.dev.rtsoft.ru>
On Apr 29, 2008, at 11:41 AM, Anton Vorontsov wrote:
> This patch adds pcie node which is resposible for PCI-E x8 slot
> functioning. Though, this was tested using only x1 SKY2 NIC.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> arch/powerpc/boot/dts/mpc8610_hpcd.dts | 21 +++++++++++++++++++++
> 1 files changed, 21 insertions(+), 0 deletions(-)
applied.
- k
^ permalink raw reply
* Re: [PATCH] rapidio: fix current kernel-doc notation
From: Kumar Gala @ 2008-05-01 3:57 UTC (permalink / raw)
To: Randy Dunlap
Cc: lkml, linuxppc-dev, Paul Mackerras, Andrew Morton, torvalds,
Wei.Zhang
In-Reply-To: <20080430164558.03b5f517.randy.dunlap@oracle.com>
On Apr 30, 2008, at 6:45 PM, Randy Dunlap wrote:
> From: Randy Dunlap <randy.dunlap@oracle.com>
>
> Fix current (-git16) missing docbook/kernel-doc notation in RapidIO
> files.
>
> Warning(linux-2.6.25-git16//include/linux/rio.h:187): No description
> found for parameter 'sys_size'
> Warning(linux-2.6.25-git16//include/linux/rio.h:187): No description
> found for parameter 'phy_type'
>
> Warning(linux-2.6.25-git16//arch/powerpc/sysdev/fsl_rio.c:188): No
> description found for parameter 'mport'
> Warning(linux-2.6.25-git16//arch/powerpc/sysdev/fsl_rio.c:224): No
> description found for parameter 'mport'
> Warning(linux-2.6.25-git16//arch/powerpc/sysdev/fsl_rio.c:245): No
> description found for parameter 'mport'
> Warning(linux-2.6.25-git16//arch/powerpc/sysdev/fsl_rio.c:270): No
> description found for parameter 'mport'
> Warning(linux-2.6.25-git16//arch/powerpc/sysdev/fsl_rio.c:311): No
> description found for parameter 'mport'
> Warning(linux-2.6.25-git16//arch/powerpc/sysdev/fsl_rio.c:996): No
> description found for parameter 'dev'
>
> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
> ---
> arch/powerpc/sysdev/fsl_rio.c | 9 +++++++--
> include/linux/rio.h | 2 ++
> 2 files changed, 9 insertions(+), 2 deletions(-)
applied.
- k
^ permalink raw reply
* Re: [PATCH 1/6] [POWERPC] sysdev: implement FSL GTM support
From: Kumar Gala @ 2008-05-01 4:00 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
In-Reply-To: <20080429190017.GA21203@polina.dev.rtsoft.ru>
On Apr 29, 2008, at 2:00 PM, Anton Vorontsov wrote:
> GTM stands for General-purpose Timers Module and able to generate
> timer{1,2,3,4} interrupts. These timers are used by the drivers that
> need time precise interrupts (like for USB transactions scheduling for
> the Freescale USB Host controller as found in some QE and CPM chips),
> or these timers could be used as wakeup events from the CPU deep-sleep
> mode.
>
> Things unimplemented:
> 1. Cascaded (32 bit) timers (1-2, 3-4).
> This is straightforward to implement when needed, two timers should
> be marked as "requested" and configured as appropriate.
> 2. Super-cascaded (64 bit) timers (1-2-3-4).
> This is also straightforward to implement when needed, all timers
> should be marked as "requested" and configured as appropriate.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> Documentation/powerpc/booting-without-of.txt | 37 +++-
> arch/powerpc/Kconfig | 5 +
> arch/powerpc/sysdev/Makefile | 1 +
> arch/powerpc/sysdev/fsl_gtm.c | 424 +++++++++++++++++
> +++++++++
> include/asm-powerpc/fsl_gtm.h | 47 +++
> 5 files changed, 513 insertions(+), 1 deletions(-)
> create mode 100644 arch/powerpc/sysdev/fsl_gtm.c
> create mode 100644 include/asm-powerpc/fsl_gtm.h
>
>
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 4e40c12..4070a78 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -538,6 +538,11 @@ config FSL_LBC
> help
> Freescale Localbus support
>
> +config FSL_GTM
> + bool
> + help
> + Freescale General-purpose Timers support
> +
what chips actually use this? just QE or 83xx?
- k
^ permalink raw reply
* [PATCH v5] [POWERPC] devres: Add devm_ioremap_prot()
From: Kumar Gala @ 2008-05-01 4:12 UTC (permalink / raw)
To: linuxppc-dev
Cc: Andrew Morton, Stephen Rothwell, htejun, Jeff Garzik, Greg KH,
linux-kernel, Emilian.Medve
From: Emil Medve <Emilian.Medve@Freescale.com>
We provide an ioremap_flags so provide a corresponding devm_ioremap_prot.
The slight name difference is at Ben Herrenschmidt request as he plans
on changing ioremap_flags to ioremap_prot in the future.
Signed-off-by: Emil Medve <Emilian.Medve@Freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Acked-by: Tejun Heo <htejun@gmail.com>
---
v4 was labeled as v3. this is fresh version against a recent linus tree
so it applies cleanly
arch/powerpc/lib/Makefile | 1 +
arch/powerpc/lib/devres.c | 42 ++++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/io.h | 8 +++++++-
include/linux/io.h | 1 +
lib/devres.c | 2 +-
5 files changed, 52 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/lib/devres.c
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 4bb023f..f1d2cdc 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_SMP) += locks.o
endif
obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o
+obj-$(CONFIG_HAS_IOMEM) += devres.o
diff --git a/arch/powerpc/lib/devres.c b/arch/powerpc/lib/devres.c
new file mode 100644
index 0000000..292115d
--- /dev/null
+++ b/arch/powerpc/lib/devres.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 Freescale Semiconductor, Inc.
+ *
+ * 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/device.h> /* devres_*(), devm_ioremap_release() */
+#include <linux/io.h> /* ioremap_flags() */
+#include <linux/module.h> /* EXPORT_SYMBOL() */
+
+/**
+ * devm_ioremap_prot - Managed ioremap_flags()
+ * @dev: Generic device to remap IO address for
+ * @offset: BUS offset to map
+ * @size: Size of map
+ * @flags: Page flags
+ *
+ * Managed ioremap_prot(). Map is automatically unmapped on driver
+ * detach.
+ */
+void __iomem *devm_ioremap_prot(struct device *dev, resource_size_t offset,
+ size_t size, unsigned long flags)
+{
+ void __iomem **ptr, *addr;
+
+ ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return NULL;
+
+ addr = ioremap_flags(offset, size, flags);
+ if (addr) {
+ *ptr = addr;
+ devres_add(dev, ptr);
+ } else
+ devres_free(ptr);
+
+ return addr;
+}
+EXPORT_SYMBOL(devm_ioremap_prot);
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index afae069..e0062d7 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -2,7 +2,7 @@
#define _ASM_POWERPC_IO_H
#ifdef __KERNEL__
-/*
+/*
* 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
@@ -18,6 +18,9 @@ extern int check_legacy_ioport(unsigned long base_port);
#define _PNPWRP 0xa79
#define PNPBIOS_BASE 0xf000
+#include <linux/device.h>
+#include <linux/io.h>
+
#include <linux/compiler.h>
#include <asm/page.h>
#include <asm/byteorder.h>
@@ -744,6 +747,9 @@ static inline void * bus_to_virt(unsigned long address)
#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
+void __iomem *devm_ioremap_prot(struct device *dev, resource_size_t offset,
+ size_t size, unsigned long flags);
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_IO_H */
diff --git a/include/linux/io.h b/include/linux/io.h
index 3a03a36..ada8c74 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -58,6 +58,7 @@ static inline void devm_ioport_unmap(struct device *dev, void __iomem *addr)
}
#endif
+void devm_ioremap_release(struct device *dev, void *res);
void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
unsigned long size);
void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
diff --git a/lib/devres.c b/lib/devres.c
index 26c87c4..72c8909 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -2,7 +2,7 @@
#include <linux/io.h>
#include <linux/module.h>
-static void devm_ioremap_release(struct device *dev, void *res)
+void devm_ioremap_release(struct device *dev, void *res)
{
iounmap(*(void __iomem **)res);
}
--
1.5.4.1
^ permalink raw reply related
* [PATCH 0/6] [POWERPC] Implement dma_*map*_attrs() and DMA_ATTR_WEAK_ORDERING, use on Cell
From: markn @ 2008-05-01 4:29 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
--
Hi Paul,
Any chance of these patches getting into .26? They were held up waiting
for the new dma_*map*_attrs() patches to go in (which made it in from -mm
on the 29th)...
Thanks!
Mark.
^ permalink raw reply
* [PATCH 1/6] [POWERPC] Add struct iommu_table argument to iommu_map_sg()
From: markn @ 2008-05-01 4:29 UTC (permalink / raw)
To: paulus; +Cc: Mark Nelson, linuxppc-dev
In-Reply-To: <20080501042949.237603158@au1.ibm.com>
Make iommu_map_sg take a struct iommu_table. It did so before commit
740c3ce66700640a6e6136ff679b067e92125794 (iommu sg merging: ppc: make
iommu respect the segment size limits).
This stops the function looking in the archdata.dma_data for the iommu
table because in the future it will be called with a device that has
no table there.
This also has the nice side effect of making iommu_map_sg() match the
other map functions.
Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---
arch/powerpc/kernel/dma_64.c | 2 +-
arch/powerpc/kernel/iommu.c | 7 +++----
include/asm-powerpc/iommu.h | 6 +++---
3 files changed, 7 insertions(+), 8 deletions(-)
Index: upstream/arch/powerpc/kernel/dma_64.c
===================================================================
--- upstream.orig/arch/powerpc/kernel/dma_64.c
+++ upstream/arch/powerpc/kernel/dma_64.c
@@ -68,7 +68,7 @@ static void dma_iommu_unmap_single(struc
static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- return iommu_map_sg(dev, sglist, nelems,
+ return iommu_map_sg(dev, dev->archdata.dma_data, sglist, nelems,
device_to_mask(dev), direction);
}
Index: upstream/arch/powerpc/kernel/iommu.c
===================================================================
--- upstream.orig/arch/powerpc/kernel/iommu.c
+++ upstream/arch/powerpc/kernel/iommu.c
@@ -267,11 +267,10 @@ static void iommu_free(struct iommu_tabl
spin_unlock_irqrestore(&(tbl->it_lock), flags);
}
-int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
- int nelems, unsigned long mask,
- enum dma_data_direction direction)
+int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
+ struct scatterlist *sglist, int nelems,
+ unsigned long mask, enum dma_data_direction direction)
{
- struct iommu_table *tbl = dev->archdata.dma_data;
dma_addr_t dma_next = 0, dma_addr;
unsigned long flags;
struct scatterlist *s, *outs, *segstart;
Index: upstream/include/asm-powerpc/iommu.h
===================================================================
--- upstream.orig/include/asm-powerpc/iommu.h
+++ upstream/include/asm-powerpc/iommu.h
@@ -79,9 +79,9 @@ extern void iommu_free_table(struct iomm
extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
int nid);
-extern int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
- int nelems, unsigned long mask,
- enum dma_data_direction direction);
+extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
+ struct scatterlist *sglist, int nelems,
+ unsigned long mask, enum dma_data_direction direction);
extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction);
--
^ permalink raw reply
* [PATCH 2/6] [POWERPC] dma: implement new dma_*map*_attrs() interfaces
From: markn @ 2008-05-01 4:29 UTC (permalink / raw)
To: paulus; +Cc: Mark Nelson, linuxppc-dev
In-Reply-To: <20080501042949.237603158@au1.ibm.com>
Update powerpc to use the new dma_*map*_attrs() interfaces. In doing so
update struct dma_mapping_ops to accept a struct dma_attrs and propagate
these changes through to all users of the code (generic IOMMU and the
64bit DMA code, and the iseries and ps3 platform code).
The old dma_*map_*() interfaces are reimplemented as calls to the
corresponding new interfaces.
Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---
arch/powerpc/Kconfig | 1
arch/powerpc/kernel/dma_64.c | 34 ++++++---
arch/powerpc/kernel/ibmebus.c | 12 ++-
arch/powerpc/kernel/iommu.c | 11 +--
arch/powerpc/platforms/iseries/iommu.c | 4 -
arch/powerpc/platforms/ps3/system-bus.c | 17 ++--
include/asm-powerpc/dma-mapping.h | 116 +++++++++++++++++++++++---------
include/asm-powerpc/iommu.h | 12 ++-
8 files changed, 144 insertions(+), 63 deletions(-)
Index: upstream/arch/powerpc/Kconfig
===================================================================
--- upstream.orig/arch/powerpc/Kconfig
+++ upstream/arch/powerpc/Kconfig
@@ -110,6 +110,7 @@ config PPC
select HAVE_KPROBES
select HAVE_KRETPROBES
select HAVE_LMB
+ select HAVE_DMA_ATTRS
config EARLY_PRINTK
bool
Index: upstream/arch/powerpc/kernel/dma_64.c
===================================================================
--- upstream.orig/arch/powerpc/kernel/dma_64.c
+++ upstream/arch/powerpc/kernel/dma_64.c
@@ -50,32 +50,38 @@ static void dma_iommu_free_coherent(stru
*/
static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr,
size_t size,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
return iommu_map_single(dev, dev->archdata.dma_data, vaddr, size,
- device_to_mask(dev), direction);
+ device_to_mask(dev), direction, attrs);
}
static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
size_t size,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
- iommu_unmap_single(dev->archdata.dma_data, dma_handle, size, direction);
+ iommu_unmap_single(dev->archdata.dma_data, dma_handle, size, direction,
+ attrs);
}
static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
- int nelems, enum dma_data_direction direction)
+ int nelems, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
return iommu_map_sg(dev, dev->archdata.dma_data, sglist, nelems,
- device_to_mask(dev), direction);
+ device_to_mask(dev), direction, attrs);
}
static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist,
- int nelems, enum dma_data_direction direction)
+ int nelems, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
- iommu_unmap_sg(dev->archdata.dma_data, sglist, nelems, direction);
+ iommu_unmap_sg(dev->archdata.dma_data, sglist, nelems, direction,
+ attrs);
}
/* We support DMA to/from any memory page via the iommu */
@@ -148,19 +154,22 @@ static void dma_direct_free_coherent(str
static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr,
size_t size,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
return virt_to_abs(ptr) + get_dma_direct_offset(dev);
}
static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr,
size_t size,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
}
static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
- int nents, enum dma_data_direction direction)
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
struct scatterlist *sg;
int i;
@@ -174,7 +183,8 @@ static int dma_direct_map_sg(struct devi
}
static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction)
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
}
Index: upstream/arch/powerpc/kernel/ibmebus.c
===================================================================
--- upstream.orig/arch/powerpc/kernel/ibmebus.c
+++ upstream/arch/powerpc/kernel/ibmebus.c
@@ -82,7 +82,8 @@ static void ibmebus_free_coherent(struct
static dma_addr_t ibmebus_map_single(struct device *dev,
void *ptr,
size_t size,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
return (dma_addr_t)(ptr);
}
@@ -90,14 +91,16 @@ static dma_addr_t ibmebus_map_single(str
static void ibmebus_unmap_single(struct device *dev,
dma_addr_t dma_addr,
size_t size,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
return;
}
static int ibmebus_map_sg(struct device *dev,
struct scatterlist *sgl,
- int nents, enum dma_data_direction direction)
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
struct scatterlist *sg;
int i;
@@ -112,7 +115,8 @@ static int ibmebus_map_sg(struct device
static void ibmebus_unmap_sg(struct device *dev,
struct scatterlist *sg,
- int nents, enum dma_data_direction direction)
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
return;
}
Index: upstream/arch/powerpc/kernel/iommu.c
===================================================================
--- upstream.orig/arch/powerpc/kernel/iommu.c
+++ upstream/arch/powerpc/kernel/iommu.c
@@ -269,7 +269,8 @@ static void iommu_free(struct iommu_tabl
int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
struct scatterlist *sglist, int nelems,
- unsigned long mask, enum dma_data_direction direction)
+ unsigned long mask, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
dma_addr_t dma_next = 0, dma_addr;
unsigned long flags;
@@ -411,7 +412,8 @@ int iommu_map_sg(struct device *dev, str
void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
- int nelems, enum dma_data_direction direction)
+ int nelems, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
struct scatterlist *sg;
unsigned long flags;
@@ -553,7 +555,7 @@ void iommu_free_table(struct iommu_table
*/
dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
void *vaddr, size_t size, unsigned long mask,
- enum dma_data_direction direction)
+ enum dma_data_direction direction, struct dma_attrs *attrs)
{
dma_addr_t dma_handle = DMA_ERROR_CODE;
unsigned long uaddr;
@@ -586,7 +588,8 @@ dma_addr_t iommu_map_single(struct devic
}
void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction direction)
+ size_t size, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
unsigned int npages;
Index: upstream/arch/powerpc/platforms/iseries/iommu.c
===================================================================
--- upstream.orig/arch/powerpc/platforms/iseries/iommu.c
+++ upstream/arch/powerpc/platforms/iseries/iommu.c
@@ -214,13 +214,13 @@ dma_addr_t iseries_hv_map(void *vaddr, s
enum dma_data_direction direction)
{
return iommu_map_single(NULL, &vio_iommu_table, vaddr, size,
- DMA_32BIT_MASK, direction);
+ DMA_32BIT_MASK, direction, NULL);
}
void iseries_hv_unmap(dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
- iommu_unmap_single(&vio_iommu_table, dma_handle, size, direction);
+ iommu_unmap_single(&vio_iommu_table, dma_handle, size, direction, NULL);
}
void __init iommu_vio_init(void)
Index: upstream/arch/powerpc/platforms/ps3/system-bus.c
===================================================================
--- upstream.orig/arch/powerpc/platforms/ps3/system-bus.c
+++ upstream/arch/powerpc/platforms/ps3/system-bus.c
@@ -550,7 +550,7 @@ static void ps3_free_coherent(struct dev
*/
static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size,
- enum dma_data_direction direction)
+ enum dma_data_direction direction, struct dma_attrs *attrs)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int result;
@@ -570,7 +570,8 @@ static dma_addr_t ps3_sb_map_single(stru
static dma_addr_t ps3_ioc0_map_single(struct device *_dev, void *ptr,
size_t size,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int result;
@@ -603,7 +604,7 @@ static dma_addr_t ps3_ioc0_map_single(st
}
static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction direction)
+ size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int result;
@@ -617,7 +618,7 @@ static void ps3_unmap_single(struct devi
}
static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl,
- int nents, enum dma_data_direction direction)
+ int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
{
#if defined(CONFIG_PS3_DYNAMIC_DMA)
BUG_ON("do");
@@ -646,14 +647,15 @@ static int ps3_sb_map_sg(struct device *
static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg,
int nents,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
BUG();
return 0;
}
static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction)
+ int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
{
#if defined(CONFIG_PS3_DYNAMIC_DMA)
BUG_ON("do");
@@ -661,7 +663,8 @@ static void ps3_sb_unmap_sg(struct devic
}
static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction)
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
BUG();
}
Index: upstream/include/asm-powerpc/dma-mapping.h
===================================================================
--- upstream.orig/include/asm-powerpc/dma-mapping.h
+++ upstream/include/asm-powerpc/dma-mapping.h
@@ -13,6 +13,7 @@
/* need struct page definitions */
#include <linux/mm.h>
#include <linux/scatterlist.h>
+#include <linux/dma-attrs.h>
#include <asm/io.h>
#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
@@ -53,13 +54,17 @@ struct dma_mapping_ops {
void (*free_coherent)(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);
dma_addr_t (*map_single)(struct device *dev, void *ptr,
- size_t size, enum dma_data_direction direction);
+ size_t size, enum dma_data_direction direction,
+ struct dma_attrs *attrs);
void (*unmap_single)(struct device *dev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction direction);
+ size_t size, enum dma_data_direction direction,
+ struct dma_attrs *attrs);
int (*map_sg)(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction);
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs);
void (*unmap_sg)(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction);
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs);
int (*dma_supported)(struct device *dev, u64 mask);
int (*set_dma_mask)(struct device *dev, u64 dma_mask);
};
@@ -109,6 +114,77 @@ static inline int dma_set_mask(struct de
return 0;
}
+static inline dma_addr_t dma_map_single_attrs(struct device *dev,
+ void *cpu_addr,
+ size_t size,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+ return dma_ops->map_single(dev, cpu_addr, size, direction, attrs);
+}
+
+static inline void dma_unmap_single_attrs(struct device *dev,
+ dma_addr_t dma_addr,
+ size_t size,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+ dma_ops->unmap_single(dev, dma_addr, size, direction, attrs);
+}
+
+static inline dma_addr_t dma_map_page_attrs(struct device *dev,
+ struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+ return dma_ops->map_single(dev, page_address(page) + offset, size,
+ direction, attrs);
+}
+
+static inline void dma_unmap_page_attrs(struct device *dev,
+ dma_addr_t dma_address,
+ size_t size,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+ dma_ops->unmap_single(dev, dma_address, size, direction, attrs);
+}
+
+static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+ return dma_ops->map_sg(dev, sg, nents, direction, attrs);
+}
+
+static inline void dma_unmap_sg_attrs(struct device *dev,
+ struct scatterlist *sg,
+ int nhwentries,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ BUG_ON(!dma_ops);
+ dma_ops->unmap_sg(dev, sg, nhwentries, direction, attrs);
+}
+
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
@@ -131,63 +207,43 @@ static inline dma_addr_t dma_map_single(
size_t size,
enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
- return dma_ops->map_single(dev, cpu_addr, size, direction);
+ return dma_map_single_attrs(dev, cpu_addr, size, direction, NULL);
}
static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
size_t size,
enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
- dma_ops->unmap_single(dev, dma_addr, size, direction);
+ dma_unmap_single_attrs(dev, dma_addr, size, direction, NULL);
}
static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
- return dma_ops->map_single(dev, page_address(page) + offset, size,
- direction);
+ return dma_map_page_attrs(dev, page, offset, size, direction, NULL);
}
static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
size_t size,
enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
- dma_ops->unmap_single(dev, dma_address, size, direction);
+ dma_unmap_page_attrs(dev, dma_address, size, direction, NULL);
}
static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
- return dma_ops->map_sg(dev, sg, nents, direction);
+ return dma_map_sg_attrs(dev, sg, nents, direction, NULL);
}
static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
int nhwentries,
enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
- dma_ops->unmap_sg(dev, sg, nhwentries, direction);
+ dma_unmap_sg_attrs(dev, sg, nhwentries, direction, NULL);
}
-
/*
* Available generic sets of operations
*/
Index: upstream/include/asm-powerpc/iommu.h
===================================================================
--- upstream.orig/include/asm-powerpc/iommu.h
+++ upstream/include/asm-powerpc/iommu.h
@@ -81,9 +81,11 @@ extern struct iommu_table *iommu_init_ta
extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
struct scatterlist *sglist, int nelems,
- unsigned long mask, enum dma_data_direction direction);
+ unsigned long mask, enum dma_data_direction direction,
+ struct dma_attrs *attrs);
extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
- int nelems, enum dma_data_direction direction);
+ int nelems, enum dma_data_direction direction,
+ struct dma_attrs *attrs);
extern void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
size_t size, dma_addr_t *dma_handle,
@@ -92,9 +94,11 @@ extern void iommu_free_coherent(struct i
void *vaddr, dma_addr_t dma_handle);
extern dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
void *vaddr, size_t size, unsigned long mask,
- enum dma_data_direction direction);
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs);
extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction direction);
+ size_t size, enum dma_data_direction direction,
+ struct dma_attrs *attrs);
extern void iommu_init_early_pSeries(void);
extern void iommu_init_early_iSeries(void);
--
^ permalink raw reply
* [PATCH 3/6] [POWERPC] dma: use the struct dma_attrs in iommu code
From: markn @ 2008-05-01 4:29 UTC (permalink / raw)
To: paulus; +Cc: Mark Nelson, linuxppc-dev
In-Reply-To: <20080501042949.237603158@au1.ibm.com>
Update iommu_alloc() to take the struct dma_attrs and pass them on to
tce_build(). This change propagates down to the tce_build functions of
all the platforms.
Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---
arch/powerpc/kernel/iommu.c | 13 ++++++++-----
arch/powerpc/platforms/cell/iommu.c | 5 +++--
arch/powerpc/platforms/iseries/iommu.c | 3 ++-
arch/powerpc/platforms/pasemi/iommu.c | 3 ++-
arch/powerpc/platforms/pseries/iommu.c | 13 ++++++++-----
arch/powerpc/sysdev/dart_iommu.c | 3 ++-
include/asm-powerpc/machdep.h | 3 ++-
7 files changed, 27 insertions(+), 16 deletions(-)
Index: upstream/arch/powerpc/kernel/iommu.c
===================================================================
--- upstream.orig/arch/powerpc/kernel/iommu.c
+++ upstream/arch/powerpc/kernel/iommu.c
@@ -186,7 +186,8 @@ static unsigned long iommu_range_alloc(s
static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
void *page, unsigned int npages,
enum dma_data_direction direction,
- unsigned long mask, unsigned int align_order)
+ unsigned long mask, unsigned int align_order,
+ struct dma_attrs *attrs)
{
unsigned long entry, flags;
dma_addr_t ret = DMA_ERROR_CODE;
@@ -205,7 +206,7 @@ static dma_addr_t iommu_alloc(struct dev
/* Put the TCEs in the HW table */
ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & IOMMU_PAGE_MASK,
- direction);
+ direction, attrs);
/* Flush/invalidate TLB caches if necessary */
@@ -336,7 +337,8 @@ int iommu_map_sg(struct device *dev, str
npages, entry, dma_addr);
/* Insert into HW table */
- ppc_md.tce_build(tbl, entry, npages, vaddr & IOMMU_PAGE_MASK, direction);
+ ppc_md.tce_build(tbl, entry, npages, vaddr & IOMMU_PAGE_MASK,
+ direction, attrs);
/* If we are in an open segment, try merging */
if (segstart != s) {
@@ -573,7 +575,8 @@ dma_addr_t iommu_map_single(struct devic
align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction,
- mask >> IOMMU_PAGE_SHIFT, align);
+ mask >> IOMMU_PAGE_SHIFT, align,
+ attrs);
if (dma_handle == DMA_ERROR_CODE) {
if (printk_ratelimit()) {
printk(KERN_INFO "iommu_alloc failed, "
@@ -642,7 +645,7 @@ void *iommu_alloc_coherent(struct device
nio_pages = size >> IOMMU_PAGE_SHIFT;
io_order = get_iommu_order(size);
mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
- mask >> IOMMU_PAGE_SHIFT, io_order);
+ mask >> IOMMU_PAGE_SHIFT, io_order, NULL);
if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order);
return NULL;
Index: upstream/arch/powerpc/platforms/cell/iommu.c
===================================================================
--- upstream.orig/arch/powerpc/platforms/cell/iommu.c
+++ upstream/arch/powerpc/platforms/cell/iommu.c
@@ -173,7 +173,8 @@ static void invalidate_tce_cache(struct
}
static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
- unsigned long uaddr, enum dma_data_direction direction)
+ unsigned long uaddr, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
int i;
unsigned long *io_pte, base_pte;
@@ -519,7 +520,7 @@ cell_iommu_setup_window(struct cbe_iommu
__set_bit(0, window->table.it_map);
tce_build_cell(&window->table, window->table.it_offset, 1,
- (unsigned long)iommu->pad_page, DMA_TO_DEVICE);
+ (unsigned long)iommu->pad_page, DMA_TO_DEVICE, NULL);
window->table.it_hint = window->table.it_blocksize;
return window;
Index: upstream/arch/powerpc/platforms/iseries/iommu.c
===================================================================
--- upstream.orig/arch/powerpc/platforms/iseries/iommu.c
+++ upstream/arch/powerpc/platforms/iseries/iommu.c
@@ -42,7 +42,8 @@
#include <asm/iseries/iommu.h>
static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
- unsigned long uaddr, enum dma_data_direction direction)
+ unsigned long uaddr, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
u64 rc;
u64 tce, rpn;
Index: upstream/arch/powerpc/platforms/pasemi/iommu.c
===================================================================
--- upstream.orig/arch/powerpc/platforms/pasemi/iommu.c
+++ upstream/arch/powerpc/platforms/pasemi/iommu.c
@@ -85,7 +85,8 @@ static int iommu_table_iobmap_inited;
static void iobmap_build(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
u32 *ip;
u32 rpn;
Index: upstream/arch/powerpc/platforms/pseries/iommu.c
===================================================================
--- upstream.orig/arch/powerpc/platforms/pseries/iommu.c
+++ upstream/arch/powerpc/platforms/pseries/iommu.c
@@ -50,7 +50,8 @@
static void tce_build_pSeries(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
u64 proto_tce;
u64 *tcep;
@@ -95,7 +96,8 @@ static unsigned long tce_get_pseries(str
static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
u64 rc;
u64 proto_tce, tce;
@@ -127,7 +129,8 @@ static DEFINE_PER_CPU(u64 *, tce_page) =
static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
u64 rc;
u64 proto_tce;
@@ -137,7 +140,7 @@ static void tce_buildmulti_pSeriesLP(str
if (npages == 1)
return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
- direction);
+ direction, attrs);
tcep = __get_cpu_var(tce_page);
@@ -149,7 +152,7 @@ static void tce_buildmulti_pSeriesLP(str
/* If allocation fails, fall back to the loop implementation */
if (!tcep)
return tce_build_pSeriesLP(tbl, tcenum, npages,
- uaddr, direction);
+ uaddr, direction, attrs);
__get_cpu_var(tce_page) = tcep;
}
Index: upstream/arch/powerpc/sysdev/dart_iommu.c
===================================================================
--- upstream.orig/arch/powerpc/sysdev/dart_iommu.c
+++ upstream/arch/powerpc/sysdev/dart_iommu.c
@@ -149,7 +149,8 @@ static void dart_flush(struct iommu_tabl
static void dart_build(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
unsigned int *dp;
unsigned int rpn;
Index: upstream/include/asm-powerpc/machdep.h
===================================================================
--- upstream.orig/include/asm-powerpc/machdep.h
+++ upstream/include/asm-powerpc/machdep.h
@@ -80,7 +80,8 @@ struct machdep_calls {
long index,
long npages,
unsigned long uaddr,
- enum dma_data_direction direction);
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs);
void (*tce_free)(struct iommu_table *tbl,
long index,
long npages);
--
^ permalink raw reply
* [PATCH 4/6] [POWERPC] Make cell_dma_dev_setup_iommu() return the iommu table
From: markn @ 2008-05-01 4:29 UTC (permalink / raw)
To: paulus; +Cc: Mark Nelson, linuxppc-dev
In-Reply-To: <20080501042949.237603158@au1.ibm.com>
Make cell_dma_dev_setup_iommu() return a pointer to the struct iommu_table
(or NULL if no table can be found) rather than putting this pointer into
dev->archdata.dma_data (let the caller do that), and rename this function
to cell_get_iommu_table() to reflect this change.
This will allow us to get the iommu table for a device that doesn't have
the table in the archdata.
Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---
arch/powerpc/platforms/cell/iommu.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
Index: upstream/arch/powerpc/platforms/cell/iommu.c
===================================================================
--- upstream.orig/arch/powerpc/platforms/cell/iommu.c
+++ upstream/arch/powerpc/platforms/cell/iommu.c
@@ -541,7 +541,7 @@ static unsigned long cell_dma_direct_off
static unsigned long dma_iommu_fixed_base;
struct dma_mapping_ops dma_iommu_fixed_ops;
-static void cell_dma_dev_setup_iommu(struct device *dev)
+static struct iommu_table *cell_get_iommu_table(struct device *dev)
{
struct iommu_window *window;
struct cbe_iommu *iommu;
@@ -556,11 +556,11 @@ static void cell_dma_dev_setup_iommu(str
printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n",
archdata->of_node ? archdata->of_node->full_name : "?",
archdata->numa_node);
- return;
+ return NULL;
}
window = list_entry(iommu->windows.next, struct iommu_window, list);
- archdata->dma_data = &window->table;
+ return &window->table;
}
static void cell_dma_dev_setup_fixed(struct device *dev);
@@ -573,7 +573,7 @@ static void cell_dma_dev_setup(struct de
if (get_dma_ops(dev) == &dma_iommu_fixed_ops)
cell_dma_dev_setup_fixed(dev);
else if (get_pci_dma_ops() == &dma_iommu_ops)
- cell_dma_dev_setup_iommu(dev);
+ archdata->dma_data = cell_get_iommu_table(dev);
else if (get_pci_dma_ops() == &dma_direct_ops)
archdata->dma_data = (void *)cell_dma_direct_offset;
else
--
^ permalink raw reply
* [PATCH 5/6] [POWERPC] Move device_to_mask() to dma-mapping.h
From: markn @ 2008-05-01 4:29 UTC (permalink / raw)
To: paulus; +Cc: Mark Nelson, linuxppc-dev
In-Reply-To: <20080501042949.237603158@au1.ibm.com>
Move device_to_mask() to dma-mapping.h because we need to use it from
outside dma_64.c in a later patch.
Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---
arch/powerpc/kernel/dma_64.c | 9 ---------
include/asm-powerpc/dma-mapping.h | 9 +++++++++
2 files changed, 9 insertions(+), 9 deletions(-)
Index: upstream/arch/powerpc/kernel/dma_64.c
===================================================================
--- upstream.orig/arch/powerpc/kernel/dma_64.c
+++ upstream/arch/powerpc/kernel/dma_64.c
@@ -15,15 +15,6 @@
* Generic iommu implementation
*/
-static inline unsigned long device_to_mask(struct device *dev)
-{
- if (dev->dma_mask && *dev->dma_mask)
- return *dev->dma_mask;
- /* Assume devices without mask can take 32 bit addresses */
- return 0xfffffffful;
-}
-
-
/* Allocates a contiguous real buffer and creates mappings over it.
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (mapping) of the first page.
Index: upstream/include/asm-powerpc/dma-mapping.h
===================================================================
--- upstream.orig/include/asm-powerpc/dma-mapping.h
+++ upstream/include/asm-powerpc/dma-mapping.h
@@ -45,6 +45,15 @@ extern void __dma_sync_page(struct page
#endif /* ! CONFIG_NOT_COHERENT_CACHE */
#ifdef CONFIG_PPC64
+
+static inline unsigned long device_to_mask(struct device *dev)
+{
+ if (dev->dma_mask && *dev->dma_mask)
+ return *dev->dma_mask;
+ /* Assume devices without mask can take 32 bit addresses */
+ return 0xfffffffful;
+}
+
/*
* DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO
*/
--
^ permalink raw reply
* [PATCH 6/6] [POWERPC] Add DMA_ATTR_WEAK_ORDERING dma attribute and use in Cell IOMMU code
From: markn @ 2008-05-01 4:29 UTC (permalink / raw)
To: paulus; +Cc: Mark Nelson, linuxppc-dev
In-Reply-To: <20080501042949.237603158@au1.ibm.com>
Introduce a new dma attriblue DMA_ATTR_WEAK_ORDERING to use weak ordering
on DMA mappings in the Cell processor. Add the code to the Cell's IOMMU
implementation to use this code.
Dynamic mappings can be weakly or strongly ordered on an individual basis
but the fixed mapping has to be either completely strong or completely weak.
This is currently decided by a kernel boot option (pass iommu_fixed=weak
for a weakly ordered fixed linear mapping, strongly ordered is the default).
Signed-off-by: Mark Nelson <markn@au1.ibm.com>
---
Documentation/DMA-attributes.txt | 9 ++
arch/powerpc/platforms/cell/iommu.c | 113 ++++++++++++++++++++++++++++++++++--
include/linux/dma-attrs.h | 1
3 files changed, 118 insertions(+), 5 deletions(-)
Index: upstream/arch/powerpc/platforms/cell/iommu.c
===================================================================
--- upstream.orig/arch/powerpc/platforms/cell/iommu.c
+++ upstream/arch/powerpc/platforms/cell/iommu.c
@@ -199,6 +199,8 @@ static void tce_build_cell(struct iommu_
base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW |
(window->ioid & IOPTE_IOID_Mask);
#endif
+ if (unlikely(dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs)))
+ base_pte &= ~IOPTE_SO_RW;
io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
@@ -539,7 +541,9 @@ static struct cbe_iommu *cell_iommu_for_
static unsigned long cell_dma_direct_offset;
static unsigned long dma_iommu_fixed_base;
-struct dma_mapping_ops dma_iommu_fixed_ops;
+
+/* iommu_fixed_is_weak is set if booted with iommu_fixed=weak */
+static int iommu_fixed_is_weak;
static struct iommu_table *cell_get_iommu_table(struct device *dev)
{
@@ -563,6 +567,98 @@ static struct iommu_table *cell_get_iomm
return &window->table;
}
+/* A coherent allocation implies strong ordering */
+
+static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+{
+ if (iommu_fixed_is_weak)
+ return iommu_alloc_coherent(dev, cell_get_iommu_table(dev),
+ size, dma_handle,
+ device_to_mask(dev), flag,
+ dev->archdata.numa_node);
+ else
+ return dma_direct_ops.alloc_coherent(dev, size, dma_handle,
+ flag);
+}
+
+static void dma_fixed_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ if (iommu_fixed_is_weak)
+ iommu_free_coherent(cell_get_iommu_table(dev), size, vaddr,
+ dma_handle);
+ else
+ dma_direct_ops.free_coherent(dev, size, vaddr, dma_handle);
+}
+
+static dma_addr_t dma_fixed_map_single(struct device *dev, void *ptr,
+ size_t size,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ return dma_direct_ops.map_single(dev, ptr, size, direction,
+ attrs);
+ else
+ return iommu_map_single(dev, cell_get_iommu_table(dev), ptr,
+ size, device_to_mask(dev), direction,
+ attrs);
+}
+
+static void dma_fixed_unmap_single(struct device *dev, dma_addr_t dma_addr,
+ size_t size,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ dma_direct_ops.unmap_single(dev, dma_addr, size, direction,
+ attrs);
+ else
+ iommu_unmap_single(cell_get_iommu_table(dev), dma_addr, size,
+ direction, attrs);
+}
+
+static int dma_fixed_map_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ return dma_direct_ops.map_sg(dev, sg, nents, direction, attrs);
+ else
+ return iommu_map_sg(dev, cell_get_iommu_table(dev), sg, nents,
+ device_to_mask(dev), direction, attrs);
+}
+
+static void dma_fixed_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ dma_direct_ops.unmap_sg(dev, sg, nents, direction, attrs);
+ else
+ iommu_unmap_sg(cell_get_iommu_table(dev), sg, nents, direction,
+ attrs);
+}
+
+static int dma_fixed_dma_supported(struct device *dev, u64 mask)
+{
+ return mask == DMA_64BIT_MASK;
+}
+
+static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask);
+
+struct dma_mapping_ops dma_iommu_fixed_ops = {
+ .alloc_coherent = dma_fixed_alloc_coherent,
+ .free_coherent = dma_fixed_free_coherent,
+ .map_single = dma_fixed_map_single,
+ .unmap_single = dma_fixed_unmap_single,
+ .map_sg = dma_fixed_map_sg,
+ .unmap_sg = dma_fixed_unmap_sg,
+ .dma_supported = dma_fixed_dma_supported,
+ .set_dma_mask = dma_set_mask_and_switch,
+};
+
static void cell_dma_dev_setup_fixed(struct device *dev);
static void cell_dma_dev_setup(struct device *dev)
@@ -919,9 +1015,16 @@ static void cell_iommu_setup_fixed_ptab(
pr_debug("iommu: mapping 0x%lx pages from 0x%lx\n", fsize, fbase);
- base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW
+ base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M
| (cell_iommu_get_ioid(np) & IOPTE_IOID_Mask);
+ if (iommu_fixed_is_weak)
+ pr_info("IOMMU: Using weak ordering for fixed mapping\n");
+ else {
+ pr_info("IOMMU: Using strong ordering for fixed mapping\n");
+ base_pte |= IOPTE_SO_RW;
+ }
+
for (uaddr = 0; uaddr < fsize; uaddr += (1 << 24)) {
/* Don't touch the dynamic region */
ioaddr = uaddr + fbase;
@@ -1037,9 +1140,6 @@ static int __init cell_iommu_fixed_mappi
cell_iommu_setup_window(iommu, np, dbase, dsize, 0);
}
- dma_iommu_fixed_ops = dma_direct_ops;
- dma_iommu_fixed_ops.set_dma_mask = dma_set_mask_and_switch;
-
dma_iommu_ops.set_dma_mask = dma_set_mask_and_switch;
set_pci_dma_ops(&dma_iommu_ops);
@@ -1053,6 +1153,9 @@ static int __init setup_iommu_fixed(char
if (strcmp(str, "off") == 0)
iommu_fixed_disabled = 1;
+ else if (strcmp(str, "weak") == 0)
+ iommu_fixed_is_weak = 1;
+
return 1;
}
__setup("iommu_fixed=", setup_iommu_fixed);
Index: upstream/Documentation/DMA-attributes.txt
===================================================================
--- upstream.orig/Documentation/DMA-attributes.txt
+++ upstream/Documentation/DMA-attributes.txt
@@ -22,3 +22,12 @@ ready and available in memory. The DMA
could race with data DMA. Mapping the memory used for completion
indications with DMA_ATTR_WRITE_BARRIER would prevent the race.
+DMA_ATTR_WEAK_ORDERING
+----------------------
+
+DMA_ATTR_WEAK_ORDERING specifies that reads and writes to the mapping
+may be weakly ordered, that is that reads and writes may pass each other.
+
+Since it is optional for platforms to implement DMA_ATTR_WEAK_ORDERING,
+those that do not will simply ignore the attribute and exhibit default
+behavior.
Index: upstream/include/linux/dma-attrs.h
===================================================================
--- upstream.orig/include/linux/dma-attrs.h
+++ upstream/include/linux/dma-attrs.h
@@ -12,6 +12,7 @@
*/
enum dma_attr {
DMA_ATTR_WRITE_BARRIER,
+ DMA_ATTR_WEAK_ORDERING,
DMA_ATTR_MAX,
};
--
^ permalink raw reply
* Please pull from 'powerpc-next' branch
From: Kumar Gala @ 2008-05-01 5:04 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
Please pull from 'powerpc-next' branch of
master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc.git powerpc-next
to receive the following updates:
arch/powerpc/boot/dts/mpc8610_hpcd.dts | 23 ++++++++++++++++++++++-
arch/powerpc/kernel/head_booke.h | 2 +-
arch/powerpc/sysdev/fsl_rio.c | 9 +++++++--
include/asm-powerpc/ptrace.h | 1 +
include/linux/rio.h | 2 ++
5 files changed, 33 insertions(+), 4 deletions(-)
Anton Vorontsov (1):
[POWERPC] 86xx: mpc8610_hpcd: add support for PCI Express x8 slot
Jason Jin (1):
[POWERPC] 86xx: Fix the wrong serial1 interrupt for 8610 board
Kumar Gala (1):
[POWERPC] Set lower flag bits in regs->trap to indicate debug level exception
Randy Dunlap (1):
[RAPIDIO] fix current kernel-doc notation
^ permalink raw reply
* powerpc boot regression
From: Tony Breeds @ 2008-05-01 5:13 UTC (permalink / raw)
To: David Miller; +Cc: linux-kernel, LinuxPPC-dev, y-goto, akpm
In-Reply-To: <20080429.231241.221824292.davem@davemloft.net>
On Tue, Apr 29, 2008 at 11:12:41PM -0700, David Miller wrote:
>
> This commit causes bootup failures on sparc64:
>
> commit 86f6dae1377523689bd8468fed2f2dd180fc0560
> Author: Yasunori Goto <y-goto@jp.fujitsu.com>
> Date: Mon Apr 28 02:13:33 2008 -0700
>
> memory hotplug: allocate usemap on the section with pgdat
<snip>
We're seeing a boot failure on powerpc. git bisect points the problem
at this commit. However reverting just this one comitt doesn't fix the
regression. I also needed to revert
04753278769f3b6c3b79a080edb52f21d83bf6e2 (memory hotplug: register
section/node id to free")
Problem seen on power4, power5 and ps3.
If the fix isn't trivial, can we get that patch series reverted?
FWIW a boot looks like:
zImage starting: loaded at 0x00400000 (sp: 0x02f5fea0)
Allocating 0xa2d4c8 bytes for kernel ...
OF version = 'IBM,SF240_332'
gunzipping (0x01400000 <- 0x00407000:0x0079aa5d)...done 0x9a8ee0 bytes
Linux/PowerPC load: root=/dev/sdc3 ro
Finalizing device tree... using OF tree (promptr=02039a68)
OF stdout device is: /vdevice/vty@30000000
Hypertas detected, assuming LPAR !
command line: root=/dev/sdc3 ro
memory layout at init:
alloc_bottom : 0000000001e32000
alloc_top : 0000000008000000
alloc_top_hi : 0000000080000000
rmo_top : 0000000008000000
ram_top : 0000000080000000
Looking for displays
instantiating rtas at 0x00000000076a1000 ... done
0000000000000000 : boot cpu 0000000000000000
copying OF device tree ...
Building dt strings...
Building dt structure...
Device tree strings 0x0000000001e33000 -> 0x0000000001e3417c
Device tree struct 0x0000000001e35000 -> 0x0000000001e3d000
Calling quiesce ...
returning from prom_init
Crash kernel location must be 0x2000000
Reserving 0MB of memory at 32MB for crashkernel (System RAM: 2048MB)
Using pSeries machine description
console [udbg0] enabled
Partition configured for 20 cpus.
CPU maps initialized for 2 threads per core
Starting Linux PPC64 #52 SMP Thu May 1 14:04:46 EST 2008
-----------------------------------------------------
ppc64_pft_size = 0x19
physicalMemorySize = 0x80000000
htab_hash_mask = 0x3ffff
-----------------------------------------------------
Initializing cgroup subsys cpuset
Linux version 2.6.25 (tony@Sprygo) (gcc version 4.0.4 20060507 (prerelease) (Debian 4.0.3-3)) #52 SMP Thu May 1 14:04:46 EST 2008
[boot]0012 Setup Arch
sparse_early_usemap_alloc: allocation failed
<snip 127 more>
EEH: No capable adapters found
PPC64 nvram contains 7168 bytes
Zone PFN ranges:
DMA 0 -> 524288
Normal 524288 -> 524288
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
0: 0 -> 524288
[boot]0015 Setup Done
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 517120
Kernel command line: root=/dev/sdc3 ro
[boot]0020 XICS Init
[boot]0021 XICS Done
PID hash table entries: 4096 (order: 12, 32768 bytes)
clocksource: timebase mult[1545815] shift[22] registered
Console: colour dummy device 80x25
console handover: boot [udbg0] -> real [hvc0]
Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes)
Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes)
Unable to handle kernel paging request for data at address 0xcf00000000030858
Faulting instruction address: 0xc0000000000c4530
Oops: Kernel access of bad area, sig: 11 [#1]
SMP NR_CPUS=32 pSeries
Modules linked in:
NIP: c0000000000c4530 LR: c0000000007e8790 CTR: 80000000001af404
REGS: c000000000987ae0 TRAP: 0300 Not tainted (2.6.25)
MSR: 8000000000009032 <EE,ME,IR,DR> CR: 24000088 XER: 20000002
DAR: cf00000000030858, DSISR: 0000000040010000
TASK = c000000000862650[0] 'swapper' THREAD: c000000000984000 CPU: 0
GPR00: 0000000020000000 c000000000987d60 c000000000981f18 cf00000000030858
GPR04: 0000000000000000 0000000000000001 0000000000000000 c0000000009f2a68
GPR08: c0000000009f2a58 00000000000001b8 0000000000000000 cf00000000030858
GPR12: 0000000000004000 c0000000009ae400 0000000000000000 0000000000000000
GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000001
GPR20: c00000007ffe8000 0000000000080000 0000000000000001 c0000000009f2848
GPR24: cf00000000030200 0000000040000000 0000000000000dc0 000000000000001d
GPR28: ffffffffe0000000 cf00000000030890 c0000000008e5088 0000000000000dde
NIP [c0000000000c4530] .__free_pages_bootmem+0xc/0xa8
LR [c0000000007e8790] .free_all_bootmem_core+0x140/0x218
Call Trace:
[c000000000987d60] [0000000001c0a438] 0x1c0a438 (unreliable)
[c000000000987e40] [c0000000007d29c8] .mem_init+0x68/0x1b0
[c000000000987ed0] [c0000000007c091c] .start_kernel+0x34c/0x45c
[c000000000987f90] [c00000000000859c] .start_here_common+0x4c/0xb0
Instruction dump:
780007c6 792907c6 7c630214 38000038 7863a302 7c6301d2 4d820020 7c634a14
4bffffa0 7c862379 7c6b1b78 40820028 <e8030000> 39200000 7800a842 78005800
---[ end trace 8640abe69a316dee ]---
Kernel panic - not syncing: Attempted to kill the idle task!
Rebooting in 180 seconds..
Yours Tony
linux.conf.au http://www.marchsouth.org/
Jan 19 - 24 2009 The Australian Linux Technical Conference!
^ permalink raw reply
* Re: Please pull from 'powerpc-next' branch
From: Paul Mackerras @ 2008-05-01 5:41 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0805010003510.8224@blarg.am.freescale.net>
Kumar Gala writes:
> Please pull from 'powerpc-next' branch of
>
> master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc.git powerpc-next
>
> to receive the following updates:
I assume you want me to send these on to Linus before the merge window
closes. But this one:
> Kumar Gala (1):
> [POWERPC] Set lower flag bits in regs->trap to indicate debug level exception
needs a bit more motivation, since it is very new, and the commit
message doesn't say why we want to do what the commit does. What good
thing will happen, or what bad thing will be averted, by having this
commit in 2.6.26?
Paul.
^ permalink raw reply
* Re: [PATCH] [POWERPC] Rework EXC_LEVEL_EXCEPTION_PROLOG code
From: Kumar Gala @ 2008-05-01 6:01 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18457.1279.401197.763726@cargo.ozlabs.ibm.com>
On Apr 30, 2008, at 6:47 PM, Paul Mackerras wrote:
> Kumar Gala writes:
>
>> If we don't handle reschedule or signal will we actually not function
>> properly? I assume reschedule isn't an issue, but could we lose a
>> signal?
>
> It depends on whether a critical or machine check handler can ever do
> anything to generate a signal or a reschedule. If they can't, then
> there is no problem.
They can if the come from user space. I'm question what it means to
send a signal based on receiving an async exception.
> If they can, then we have to be very careful. If a critical or
> machine check happens at a point where normal interrupts are disabled
> then we have to be extremely careful not to do anything that the code
> we've interrupted assumes can't happen - so we'd better not try to
> take any spinlocks, for example. That severely limits what the
> handler can do. It probably shouldn't even call printk, for
> instance, or wake any process up, and definitely shouldn't call
> schedule (or schedule_preempt) on the way out.
how do we provide someone stick a kprobe on such code today?
> If the critical/mcheck interrupt happens at a point where a normal
> interrupt could have happened (including when userspace is running)
> then we could treat it pretty much as a normal interrupt, including
> handling signals or reschedules on the way out if appropriate.
So we have 4 actual exceptions:
* CriticalInput (some external device signaled this. There are two
concepts of critical. One is error the other is high priority)
However this would have the same caveats as any ExternalInput handler.
* Watchdog - pretty severe if this fires.
* Debug - user space debug is pretty straight forward. However we
have features like kprobes that require kernel level support.
* MachineCheck - pretty serve if this fires.
So I'm not if there is any good way to preclude the handlers
associated with these exceptions from doing the things you listed.
- k
^ permalink raw reply
* Re: Please pull from 'powerpc-next' branch
From: Kumar Gala @ 2008-05-01 6:02 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18457.22551.705318.772517@cargo.ozlabs.ibm.com>
On May 1, 2008, at 12:41 AM, Paul Mackerras wrote:
> Kumar Gala writes:
>
>> Please pull from 'powerpc-next' branch of
>>
>> master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc.git
>> powerpc-next
>>
>> to receive the following updates:
>
> I assume you want me to send these on to Linus before the merge window
> closes. But this one:
yes.
>> Kumar Gala (1):
>> [POWERPC] Set lower flag bits in regs->trap to indicate debug
>> level exception
>
> needs a bit more motivation, since it is very new, and the commit
> message doesn't say why we want to do what the commit does. What good
> thing will happen, or what bad thing will be averted, by having this
> commit in 2.6.26?
There's no harm either way with this one. It can wait for post
2.6.26, but its pretty trivial.
- k
^ permalink raw reply
* [POWERPC] Bolt in SLB entry for kernel stack on secondary cpus
From: Paul Mackerras @ 2008-05-01 6:04 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-kernel
This fixes a regression reported by Kamalesh Bulabel where a POWER4
machine would crash because of an SLB miss at a point where the SLB
miss exception was unrecoverable. This regression is tracked at:
http://bugzilla.kernel.org/show_bug.cgi?id=10082
SLB misses at such points shouldn't happen because the kernel stack is
the only memory accessed other than things in the first segment of the
linear mapping (which is mapped at all times by entry 0 of the SLB).
The context switch code ensures that SLB entry 2 covers the kernel
stack, if it is not already covered by entry 0. None of entries 0
to 2 are ever replaced by the SLB miss handler.
Where this went wrong is that the context switch code assumes it
doesn't have to write to SLB entry 2 if the new kernel stack is in the
same segment as the old kernel stack, since entry 2 should already be
correct. However, when we start up a secondary cpu, it calls
slb_initialize, which doesn't set up entry 2. This is correct for
the boot cpu, where we will be using a stack in the kernel BSS at this
point (i.e. init_thread_union), but not necessarily for secondary
cpus, whose initial stack can be allocated anywhere. This doesn't
cause any immediate problem since the SLB miss handler will just
create an SLB entry somewhere else to cover the initial stack.
In fact it's possible for the cpu to go quite a long time without SLB
entry 2 being valid. Eventually, though, the entry created by the SLB
miss handler will get overwritten by some other entry, and if the next
access to the stack is at an unrecoverable point, we get the crash.
This fixes the problem by making slb_initialize create a suitable
entry for the kernel stack, if we are on a secondary cpu and the stack
isn't covered by SLB entry 0. This requires initializing the
get_paca()->kstack field earlier, so I do that in smp_create_idle
where the current field is initialized. This also abstracts a bit of
the computation that mk_esid_data in slb.c does so that it can be used
in slb_initialize.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index be35ffa..1457aa0 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -386,6 +386,8 @@ static void __init smp_create_idle(unsigned int cpu)
panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
#ifdef CONFIG_PPC64
paca[cpu].__current = p;
+ paca[cpu].kstack = (unsigned long) task_thread_info(p)
+ + THREAD_SIZE - STACK_FRAME_OVERHEAD;
#endif
current_set[cpu] = task_thread_info(p);
task_thread_info(p)->cpu = cpu;
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
index 906daed..b2c43d0 100644
--- a/arch/powerpc/mm/slb.c
+++ b/arch/powerpc/mm/slb.c
@@ -44,13 +44,13 @@ static void slb_allocate(unsigned long ea)
slb_allocate_realmode(ea);
}
+#define slb_esid_mask(ssize) \
+ (((ssize) == MMU_SEGSIZE_256M)? ESID_MASK: ESID_MASK_1T)
+
static inline unsigned long mk_esid_data(unsigned long ea, int ssize,
unsigned long slot)
{
- unsigned long mask;
-
- mask = (ssize == MMU_SEGSIZE_256M)? ESID_MASK: ESID_MASK_1T;
- return (ea & mask) | SLB_ESID_V | slot;
+ return (ea & slb_esid_mask(ssize)) | SLB_ESID_V | slot;
}
#define slb_vsid_shift(ssize) \
@@ -301,11 +301,16 @@ void slb_initialize(void)
create_shadowed_slbe(VMALLOC_START, mmu_kernel_ssize, vflags, 1);
+ /* For the boot cpu, we're running on the stack in init_thread_union,
+ * which is in the first segment of the linear mapping, and also
+ * get_paca()->kstack hasn't been initialized yet.
+ * For secondary cpus, we need to bolt the kernel stack entry now.
+ */
slb_shadow_clear(2);
+ if (raw_smp_processor_id() > 0 &&
+ (get_paca()->kstack & slb_esid_mask(mmu_kernel_ssize)) > PAGE_OFFSET)
+ create_shadowed_slbe(get_paca()->kstack,
+ mmu_kernel_ssize, lflags, 2);
- /* We don't bolt the stack for the time being - we're in boot,
- * so the stack is in the bolted segment. By the time it goes
- * elsewhere, we'll call _switch() which will bolt in the new
- * one. */
asm volatile("isync":::"memory");
}
^ permalink raw reply related
* Re: drivers/net/fec_8xx config problem
From: Vitaly Bordug @ 2008-05-01 5:47 UTC (permalink / raw)
To: Scott Wood; +Cc: jengelh, linuxppc-dev@ozlabs.org list
In-Reply-To: <20080430192329.GA9150@ld0162-tx32.am.freescale.net>
On Wed, 30 Apr 2008 14:23:29 -0500
Scott Wood wrote:
> On Wed, Apr 30, 2008 at 02:24:19PM -0500, Becky Bruce wrote:
> >
> > On Apr 30, 2008, at 2:20 PM, Scott Wood wrote:
> > >On Wed, Apr 30, 2008 at 02:19:21PM -0500, Becky Bruce wrote:
> > >>I just noticed that the fec_8xx driver is not currently reachable
> > >>via menuconfig because it depends on 8XX instead of 8xx.
> > >[snip]
> > >>Since nobody has noticed this problem, I'm wondering if this
> > >>driver is still in (infrequent) use, or if it's been superseded
> > >>and should be removed, or if I'm just completely missing
> > >>something with respect to the use of "8XX" instead of "8xx".
> > >
> > >It's been superseded by drivers/net/fs_enet.
> >
> > Is there any reason we haven't removed it?
>
> To keep arch/ppc/8xx_io company? :-)
>
> > If not, I can push a patch to yank it.
>
> I have no objection.
I am OK with this too. Should have been done long ago, but who likes janitorial stuff :)
-Vitaly
^ permalink raw reply
* [PATCH v2 2/3] [POWERPC] Rework EXC_LEVEL_EXCEPTION_PROLOG code
From: Kumar Gala @ 2008-05-01 6:29 UTC (permalink / raw)
To: paulus, benh; +Cc: linuxppc-dev
In-Reply-To: <1209623369-4592-1-git-send-email-galak@kernel.crashing.org>
* Cleanup the code a bit my allocating an INT_FRAME on our exception
stack there by make references go from GPR11-INT_FRAME_SIZE(r8) to
just GPR11(r8)
* simplify {lvl}_transfer_to_handler code by moving the copying of the
temp registers we use if we come from user space into the PROLOG
* If the exception came from kernel mode copy thread_info flags,
preempt, and task pointer from the process thread_info.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
* Fixed commit comment
* reworked asm code a bit for possible performance improvement (having a second
temp regsiter to load/store from).
arch/powerpc/kernel/entry_32.S | 13 ---------
arch/powerpc/kernel/head_booke.h | 52 ++++++++++++++++++++++++--------------
2 files changed, 33 insertions(+), 32 deletions(-)
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 0c8614d..816dd54 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -44,29 +44,16 @@
#endif
#ifdef CONFIG_BOOKE
-#include "head_booke.h"
-#define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level) \
- mtspr exc_level##_SPRG,r8; \
- BOOKE_LOAD_EXC_LEVEL_STACK(exc_level); \
- lwz r0,GPR10-INT_FRAME_SIZE(r8); \
- stw r0,GPR10(r11); \
- lwz r0,GPR11-INT_FRAME_SIZE(r8); \
- stw r0,GPR11(r11); \
- mfspr r8,exc_level##_SPRG
-
.globl mcheck_transfer_to_handler
mcheck_transfer_to_handler:
- TRANSFER_TO_HANDLER_EXC_LEVEL(MCHECK)
b transfer_to_handler_full
.globl debug_transfer_to_handler
debug_transfer_to_handler:
- TRANSFER_TO_HANDLER_EXC_LEVEL(DEBUG)
b transfer_to_handler_full
.globl crit_transfer_to_handler
crit_transfer_to_handler:
- TRANSFER_TO_HANDLER_EXC_LEVEL(CRIT)
/* fall through */
#endif
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
index 9eacf4c..667c78e 100644
--- a/arch/powerpc/kernel/head_booke.h
+++ b/arch/powerpc/kernel/head_booke.h
@@ -78,12 +78,12 @@
slwi r8,r8,2; \
addis r8,r8,level##_STACK_BASE@ha; \
lwz r8,level##_STACK_BASE@l(r8); \
- addi r8,r8,THREAD_SIZE;
+ addi r8,r8,THREAD_SIZE-INT_FRAME_SIZE;
#else
#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
lis r8,level##_STACK_BASE@ha; \
lwz r8,level##_STACK_BASE@l(r8); \
- addi r8,r8,THREAD_SIZE;
+ addi r8,r8,THREAD_SIZE-INT_FRAME_SIZE;
#endif
/*
@@ -97,22 +97,36 @@
#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \
mtspr exc_level##_SPRG,r8; \
BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
- stw r10,GPR10-INT_FRAME_SIZE(r8); \
- stw r11,GPR11-INT_FRAME_SIZE(r8); \
- mfcr r10; /* save CR in r10 for now */\
- mfspr r11,exc_level_srr1; /* check whether user or kernel */\
- andi. r11,r11,MSR_PR; \
- mr r11,r8; \
- mfspr r8,exc_level##_SPRG; \
- beq 1f; \
- /* COMING FROM USER MODE */ \
+ stw r9,GPR9(r8); /* save various registers */\
+ mfcr r9; /* save CR in r9 for now */\
+ stw r10,GPR10(r8); \
+ stw r11,GPR11(r8); \
+ stw r9,_CCR(r8); /* save CR on stack */\
+ mfspr r10,exc_level_srr1; /* check whether user or kernel */\
+ andi. r10,r10,MSR_PR; \
mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
- addi r11,r11,THREAD_SIZE; \
-1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
- stw r10,_CCR(r11); /* save various registers */\
- stw r12,GPR12(r11); \
+ addi r11,r11,THREAD_SIZE-INT_FRAME_SIZE; /* Alloc exception frm */\
+ beq 1f; \
+ /* COMING FROM USER MODE */ \
+ stw r9,_CCR(r11); /* save CR */\
+ lwz r10,GPR10(r8); /* copy regs from exception stack */\
+ lwz r9,GPR9(r8); \
+ stw r10,GPR10(r11); \
+ lwz r10,GPR11(r8); \
stw r9,GPR9(r11); \
+ stw r10,GPR11(r11); \
+ b 2f; \
+ /* COMING FROM PRIV MODE */ \
+1: lwz r9,TI_FLAGS-THREAD_SIZE(r11); \
+ lwz r10,TI_PREEMPT-THREAD_SIZE(r11); \
+ stw r9,TI_FLAGS-THREAD_SIZE(r8); \
+ stw r10,TI_PREEMPT-THREAD_SIZE(r8); \
+ lwz r9,TI_TASK-THREAD_SIZE(r11); \
+ stw r9,TI_TASK-THREAD_SIZE(r8); \
+ mr r11,r8; \
+2: mfspr r8,exc_level##_SPRG; \
+ stw r12,GPR12(r11); /* save various registers */\
mflr r10; \
stw r10,_LINK(r11); \
mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
@@ -255,8 +269,8 @@ label:
lwz r12,GPR12(r11); \
mtspr DEBUG_SPRG,r8; \
BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \
- lwz r10,GPR10-INT_FRAME_SIZE(r8); \
- lwz r11,GPR11-INT_FRAME_SIZE(r8); \
+ lwz r10,GPR10(r8); \
+ lwz r11,GPR11(r8); \
mfspr r8,DEBUG_SPRG; \
\
RFDI; \
@@ -308,8 +322,8 @@ label:
lwz r12,GPR12(r11); \
mtspr CRIT_SPRG,r8; \
BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \
- lwz r10,GPR10-INT_FRAME_SIZE(r8); \
- lwz r11,GPR11-INT_FRAME_SIZE(r8); \
+ lwz r10,GPR10(r8); \
+ lwz r11,GPR11(r8); \
mfspr r8,CRIT_SPRG; \
\
rfci; \
--
1.5.4.1
^ permalink raw reply related
* [PATCH v2 1/3] [POWERPC] Move to runtime allocated exception stacks
From: Kumar Gala @ 2008-05-01 6:29 UTC (permalink / raw)
To: paulus, benh; +Cc: linuxppc-dev
For the additonal exception levels (critical, debug, machine check) on
40x/book-e we were using "static" allocations of the stack in the
associated head.S.
Move to a runtime allocation to make the code a bit easier to read as
we mimic how we handle IRQ stacks. Its also a bit easier to setup the
stack with a "dummy" thread_info in C code.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
Renamed STACK_TOP to STACK_BASE to make this a bit more clear.
- k
arch/powerpc/kernel/head_40x.S | 14 ++------------
arch/powerpc/kernel/head_44x.S | 9 ---------
arch/powerpc/kernel/head_booke.h | 29 +++++++++++------------------
arch/powerpc/kernel/head_fsl_booke.S | 9 ---------
arch/powerpc/kernel/irq.c | 33 +++++++++++++++++++++++++++++++++
arch/powerpc/kernel/setup_32.c | 24 ++++++++++++++++++++++++
include/asm-powerpc/irq.h | 13 +++++++++++++
7 files changed, 83 insertions(+), 48 deletions(-)
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S
index 8552e67..ca75eaf 100644
--- a/arch/powerpc/kernel/head_40x.S
+++ b/arch/powerpc/kernel/head_40x.S
@@ -148,8 +148,8 @@ _ENTRY(crit_r11)
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_SRR3; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
- lis r11,critical_stack_top@h; \
- ori r11,r11,critical_stack_top@l; \
+ lis r11,critirq_ctx@ha; \
+ lwz r11,critirq_ctx@l(r11); \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
@@ -996,16 +996,6 @@ empty_zero_page:
swapper_pg_dir:
.space PGD_TABLE_SIZE
-
-/* Stack for handling critical exceptions from kernel mode */
- .section .bss
- .align 12
-exception_stack_bottom:
- .space 4096
-critical_stack_top:
- .globl exception_stack_top
-exception_stack_top:
-
/* Room for two PTE pointers, usually the kernel and current user pointers
* to their respective root page table.
*/
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index b84ec6a..2041248 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -730,15 +730,6 @@ empty_zero_page:
swapper_pg_dir:
.space PGD_TABLE_SIZE
-/* Reserved 4k for the critical exception stack & 4k for the machine
- * check stack per CPU for kernel mode exceptions */
- .section .bss
- .align 12
-exception_stack_bottom:
- .space BOOKE_EXCEPTION_STACK_SIZE
- .globl exception_stack_top
-exception_stack_top:
-
/*
* Room for two PTE pointers, usually the kernel and current user pointers
* to their respective root page table.
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
index 721faef..9eacf4c 100644
--- a/arch/powerpc/kernel/head_booke.h
+++ b/arch/powerpc/kernel/head_booke.h
@@ -43,9 +43,7 @@
SAVE_2GPRS(7, r11)
/* To handle the additional exception priority levels on 40x and Book-E
- * processors we allocate a 4k stack per additional priority level. The various
- * head_xxx.S files allocate space (exception_stack_top) for each priority's
- * stack times the number of CPUs
+ * processors we allocate a stack per additional priority level.
*
* On 40x critical is the only additional level
* On 44x/e500 we have critical and machine check
@@ -61,36 +59,31 @@
* going to critical or their own debug level we aren't currently
* providing configurations that micro-optimize space usage.
*/
-#ifdef CONFIG_44x
-#define NUM_EXCEPTION_LVLS 2
-#else
-#define NUM_EXCEPTION_LVLS 3
-#endif
-#define BOOKE_EXCEPTION_STACK_SIZE (4096 * NUM_EXCEPTION_LVLS)
/* CRIT_SPRG only used in critical exception handling */
#define CRIT_SPRG SPRN_SPRG2
/* MCHECK_SPRG only used in machine check exception handling */
#define MCHECK_SPRG SPRN_SPRG6W
-#define MCHECK_STACK_TOP (exception_stack_top - 4096)
-#define CRIT_STACK_TOP (exception_stack_top)
+#define MCHECK_STACK_BASE mcheckirq_ctx
+#define CRIT_STACK_BASE critirq_ctx
/* only on e200 for now */
-#define DEBUG_STACK_TOP (exception_stack_top - 8192)
+#define DEBUG_STACK_BASE dbgirq_ctx
#define DEBUG_SPRG SPRN_SPRG6W
#ifdef CONFIG_SMP
#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
mfspr r8,SPRN_PIR; \
- mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
- neg r8,r8; \
- addis r8,r8,level##_STACK_TOP@ha; \
- addi r8,r8,level##_STACK_TOP@l
+ slwi r8,r8,2; \
+ addis r8,r8,level##_STACK_BASE@ha; \
+ lwz r8,level##_STACK_BASE@l(r8); \
+ addi r8,r8,THREAD_SIZE;
#else
#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
- lis r8,level##_STACK_TOP@h; \
- ori r8,r8,level##_STACK_TOP@l
+ lis r8,level##_STACK_BASE@ha; \
+ lwz r8,level##_STACK_BASE@l(r8); \
+ addi r8,r8,THREAD_SIZE;
#endif
/*
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index e581524..503f860 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -1080,15 +1080,6 @@ empty_zero_page:
swapper_pg_dir:
.space PGD_TABLE_SIZE
-/* Reserved 4k for the critical exception stack & 4k for the machine
- * check stack per CPU for kernel mode exceptions */
- .section .bss
- .align 12
-exception_stack_bottom:
- .space BOOKE_EXCEPTION_STACK_SIZE * NR_CPUS
- .globl exception_stack_top
-exception_stack_top:
-
/*
* Room for two PTE pointers, usually the kernel and current user pointers
* to their respective root page table.
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 2f73f70..b519975 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -356,9 +356,42 @@ void __init init_IRQ(void)
{
if (ppc_md.init_IRQ)
ppc_md.init_IRQ();
+
+ exc_lvl_ctx_init();
+
irq_ctx_init();
}
+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
+struct thread_info *critirq_ctx[NR_CPUS] __read_mostly;
+struct thread_info *dbgirq_ctx[NR_CPUS] __read_mostly;
+struct thread_info *mcheckirq_ctx[NR_CPUS] __read_mostly;
+
+void exc_lvl_ctx_init(void)
+{
+ struct thread_info *tp;
+ int i;
+
+ for_each_possible_cpu(i) {
+ memset((void *)critirq_ctx[i], 0, THREAD_SIZE);
+ tp = critirq_ctx[i];
+ tp->cpu = i;
+ tp->preempt_count = 0;
+
+#ifdef CONFIG_BOOKE
+ memset((void *)dbgirq_ctx[i], 0, THREAD_SIZE);
+ tp = dbgirq_ctx[i];
+ tp->cpu = i;
+ tp->preempt_count = 0;
+
+ memset((void *)mcheckirq_ctx[i], 0, THREAD_SIZE);
+ tp = mcheckirq_ctx[i];
+ tp->cpu = i;
+ tp->preempt_count = HARDIRQ_OFFSET;
+#endif
+ }
+}
+#endif
#ifdef CONFIG_IRQSTACKS
struct thread_info *softirq_ctx[NR_CPUS] __read_mostly;
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 5112a4a..bef0be3 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -248,6 +248,28 @@ static void __init irqstack_early_init(void)
#define irqstack_early_init()
#endif
+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
+static void __init exc_lvl_early_init(void)
+{
+ unsigned int i;
+
+ /* interrupt stacks must be in lowmem, we get that for free on ppc32
+ * as the lmb is limited to lowmem by LMB_REAL_LIMIT */
+ for_each_possible_cpu(i) {
+ critirq_ctx[i] = (struct thread_info *)
+ __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
+#ifdef CONFIG_BOOKE
+ dbgirq_ctx[i] = (struct thread_info *)
+ __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
+ mcheckirq_ctx[i] = (struct thread_info *)
+ __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
+#endif
+ }
+}
+#else
+#define exc_lvl_early_init()
+#endif
+
/* Warning, IO base is not yet inited */
void __init setup_arch(char **cmdline_p)
{
@@ -305,6 +327,8 @@ void __init setup_arch(char **cmdline_p)
init_mm.end_data = (unsigned long) _edata;
init_mm.brk = klimit;
+ exc_lvl_early_init();
+
irqstack_early_init();
/* set up the bootmem stuff with available memory */
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 5089deb..1ef8e30 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -619,6 +619,19 @@ struct pt_regs;
#define __ARCH_HAS_DO_SOFTIRQ
+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
+/*
+ * Per-cpu stacks for handling critical, debug and machine check
+ * level interrupts.
+ */
+extern struct thread_info *critirq_ctx[NR_CPUS];
+extern struct thread_info *dbgirq_ctx[NR_CPUS];
+extern struct thread_info *mcheckirq_ctx[NR_CPUS];
+extern void exc_lvl_ctx_init(void);
+#else
+#define exc_lvl_ctx_init()
+#endif
+
#ifdef CONFIG_IRQSTACKS
/*
* Per-cpu stacks for handling hard and soft interrupts.
--
1.5.4.1
^ permalink raw reply related
* [PATCH v3 3/3] [POWERPC] 40x/Book-E: Save/restore volatile exception registers
From: Kumar Gala @ 2008-05-01 6:29 UTC (permalink / raw)
To: paulus, benh; +Cc: linuxppc-dev
In-Reply-To: <1209623369-4592-2-git-send-email-galak@kernel.crashing.org>
On machines with more than one exception level any system register that
might be modified by the "normal" exception level needs to be saved and
restored on taking a higher level exception. We already are saving
and restoring ESR and DEAR.
For critical level add SRR0/1.
For debug level add CSRR0/1 and SRR0/1.
For machine check level add DSRR0/1, CSRR0/1, and SRR0/1.
On FSL Book-E parts we always save/restore the MAS registers for critical,
debug, and machine check level exceptions. On 44x we always save/restore
the MMUCR.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
* Added saving/restoring of 44x MMUCR.
arch/powerpc/kernel/asm-offsets.c | 27 +++++++++++
arch/powerpc/kernel/entry_32.S | 93 ++++++++++++++++++++++++++++++++++++-
arch/powerpc/kernel/head_40x.S | 4 ++
arch/powerpc/kernel/head_booke.h | 24 +++++++++-
4 files changed, 144 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index ec9228d..c106f1f 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -52,6 +52,15 @@
#include <asm/iseries/alpaca.h>
#endif
+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
+#include "head_booke.h"
+#endif
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
int main(void)
{
DEFINE(THREAD, offsetof(struct task_struct, thread));
@@ -242,6 +251,24 @@ int main(void)
DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8);
#endif /* CONFIG_PPC64 */
+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
+ DEFINE(EXC_LVL_SIZE, STACK_EXC_LVL_FRAME_SIZE);
+ DEFINE(MAS0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas0));
+ /* we overload MMUCR for 44x on MAS0 since they are mutually exclusive */
+ DEFINE(MMUCR, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas0));
+ DEFINE(MAS1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas1));
+ DEFINE(MAS2, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas2));
+ DEFINE(MAS3, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas3));
+ DEFINE(MAS6, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas6));
+ DEFINE(MAS7, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas7));
+ DEFINE(_SRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, srr0));
+ DEFINE(_SRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, srr1));
+ DEFINE(_CSRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, csrr0));
+ DEFINE(_CSRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, csrr1));
+ DEFINE(_DSRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, dsrr0));
+ DEFINE(_DSRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, dsrr1));
+#endif
+
DEFINE(CLONE_VM, CLONE_VM);
DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 816dd54..2cd7ecc 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -46,14 +46,46 @@
#ifdef CONFIG_BOOKE
.globl mcheck_transfer_to_handler
mcheck_transfer_to_handler:
- b transfer_to_handler_full
+ mfspr r0,SPRN_DSRR0
+ stw r0,_DSRR0(r11)
+ mfspr r0,SPRN_DSRR1
+ stw r0,_DSRR1(r11)
+ /* fall through */
.globl debug_transfer_to_handler
debug_transfer_to_handler:
- b transfer_to_handler_full
+ mfspr r0,SPRN_CSRR0
+ stw r0,_CSRR0(r11)
+ mfspr r0,SPRN_CSRR1
+ stw r0,_CSRR1(r11)
+ /* fall through */
.globl crit_transfer_to_handler
crit_transfer_to_handler:
+#ifdef CONFIG_FSL_BOOKE
+ mfspr r0,SPRN_MAS0
+ stw r0,MAS0(r11)
+ mfspr r0,SPRN_MAS1
+ stw r0,MAS1(r11)
+ mfspr r0,SPRN_MAS2
+ stw r0,MAS2(r11)
+ mfspr r0,SPRN_MAS3
+ stw r0,MAS3(r11)
+ mfspr r0,SPRN_MAS6
+ stw r0,MAS6(r11)
+#ifdef CONFIG_PHYS_64BIT
+ mfspr r0,SPRN_MAS7
+ stw r0,MAS7(r11)
+#endif /* CONFIG_PHYS_64BIT */
+#endif /* CONFIG_FSL_BOOKE */
+#ifdef CONFIG_44x
+ mfspr r0,SPRN_MMUCR
+ stw r0,MMUCR(r11)
+#endif
+ mfspr r0,SPRN_SRR0
+ stw r0,_SRR0(r11)
+ mfspr r0,SPRN_SRR1
+ stw r0,_SRR1(r11)
/* fall through */
#endif
@@ -64,6 +96,10 @@ crit_transfer_to_handler:
stw r0,GPR10(r11)
lwz r0,crit_r11@l(0)
stw r0,GPR11(r11)
+ mfspr r0,SPRN_SRR0
+ stw r0,crit_srr0@l(0)
+ mfspr r0,SPRN_SRR1
+ stw r0,crit_srr1@l(0)
/* fall through */
#endif
@@ -846,17 +882,70 @@ exc_exit_restart_end:
exc_lvl_rfi; \
b .; /* prevent prefetch past exc_lvl_rfi */
+#define RESTORE_xSRR(exc_lvl_srr0, exc_lvl_srr1) \
+ lwz r9,_##exc_lvl_srr0(r1); \
+ lwz r10,_##exc_lvl_srr1(r1); \
+ mtspr SPRN_##exc_lvl_srr0,r9; \
+ mtspr SPRN_##exc_lvl_srr1,r10;
+
+#if defined(CONFIG_FSL_BOOKE)
+#ifdef CONFIG_PHYS_64BIT
+#define RESTORE_MAS7 \
+ lwz r11,MAS7(r1); \
+ mtspr SPRN_MAS7,r11;
+#else
+#define RESTORE_MAS7
+#endif /* CONFIG_PHYS_64BIT */
+#define RESTORE_MMU_REGS \
+ lwz r9,MAS0(r1); \
+ lwz r10,MAS1(r1); \
+ lwz r11,MAS2(r1); \
+ mtspr SPRN_MAS0,r9; \
+ lwz r9,MAS3(r1); \
+ mtspr SPRN_MAS1,r10; \
+ lwz r10,MAS6(r1); \
+ mtspr SPRN_MAS2,r11; \
+ mtspr SPRN_MAS3,r9; \
+ mtspr SPRN_MAS6,r10; \
+ RESTORE_MAS7;
+#elif defined(CONFIG_44x)
+#define RESTORE_MMU_REGS \
+ lwz r9,MMUCR(r1); \
+ mtspr SPRN_MMUCR,r9; \
+#else
+#define RESTORE_MMU_REGS
+#endif
+
+#ifdef CONFIG_40x
.globl ret_from_crit_exc
ret_from_crit_exc:
+ lwz r9,crit_srr0@l(0);
+ lwz r10,crit_srr1@l(0);
+ mtspr SPRN_SRR0,r9;
+ mtspr SPRN_SRR1,r10;
RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
+#endif /* CONFIG_40x */
#ifdef CONFIG_BOOKE
+ .globl ret_from_crit_exc
+ret_from_crit_exc:
+ RESTORE_xSRR(SRR0,SRR1);
+ RESTORE_MMU_REGS;
+ RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
+
.globl ret_from_debug_exc
ret_from_debug_exc:
+ RESTORE_xSRR(SRR0,SRR1);
+ RESTORE_xSRR(CSRR0,CSRR1);
+ RESTORE_MMU_REGS;
RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI)
.globl ret_from_mcheck_exc
ret_from_mcheck_exc:
+ RESTORE_xSRR(SRR0,SRR1);
+ RESTORE_xSRR(CSRR0,CSRR1);
+ RESTORE_xSRR(DSRR0,DSRR1);
+ RESTORE_MMU_REGS;
RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
#endif /* CONFIG_BOOKE */
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S
index ca75eaf..3c819a1 100644
--- a/arch/powerpc/kernel/head_40x.S
+++ b/arch/powerpc/kernel/head_40x.S
@@ -93,6 +93,10 @@ _ENTRY(crit_r10)
.space 4
_ENTRY(crit_r11)
.space 4
+_ENTRY(crit_srr0)
+ .space 4
+_ENTRY(crit_srr1)
+ .space 4
/*
* Exception vector entry code. This code runs with address translation
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
index 667c78e..9c81efc 100644
--- a/arch/powerpc/kernel/head_booke.h
+++ b/arch/powerpc/kernel/head_booke.h
@@ -78,12 +78,12 @@
slwi r8,r8,2; \
addis r8,r8,level##_STACK_BASE@ha; \
lwz r8,level##_STACK_BASE@l(r8); \
- addi r8,r8,THREAD_SIZE-INT_FRAME_SIZE;
+ addi r8,r8,THREAD_SIZE-INT_FRAME_SIZE-EXC_LVL_SIZE;
#else
#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
lis r8,level##_STACK_BASE@ha; \
lwz r8,level##_STACK_BASE@l(r8); \
- addi r8,r8,THREAD_SIZE-INT_FRAME_SIZE;
+ addi r8,r8,THREAD_SIZE-INT_FRAME_SIZE-EXC_LVL_SIZE;
#endif
/*
@@ -374,4 +374,24 @@ label:
addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
+#ifndef __ASSEMBLY__
+/* ensure this structure is always sized to a multiple of the stack alignment */
+struct exception_regs {
+ unsigned long mas0;
+ unsigned long mas1;
+ unsigned long mas2;
+ unsigned long mas3;
+ unsigned long mas6;
+ unsigned long mas7;
+ unsigned long srr0;
+ unsigned long srr1;
+ unsigned long csrr0;
+ unsigned long csrr1;
+ unsigned long dsrr0;
+ unsigned long dsrr1;
+};
+
+#define STACK_EXC_LVL_FRAME_SIZE (sizeof (struct exception_regs))
+
+#endif /* __ASSEMBLY__ */
#endif /* __HEAD_BOOKE_H__ */
--
1.5.4.1
^ permalink raw reply related
* Re: [PATCH] [POWERPC] Rework EXC_LEVEL_EXCEPTION_PROLOG code
From: Benjamin Herrenschmidt @ 2008-05-01 7:53 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <A9B566F7-D00B-4202-9B85-427C38EE6070@kernel.crashing.org>
On Thu, 2008-05-01 at 01:01 -0500, Kumar Gala wrote:
> On Apr 30, 2008, at 6:47 PM, Paul Mackerras wrote:
> > Kumar Gala writes:
> >
> >> If we don't handle reschedule or signal will we actually not function
> >> properly? I assume reschedule isn't an issue, but could we lose a
> >> signal?
> >
> > It depends on whether a critical or machine check handler can ever do
> > anything to generate a signal or a reschedule. If they can't, then
> > there is no problem.
>
> They can if the come from user space. I'm question what it means to
> send a signal based on receiving an async exception.
For "normal" async exceptions (ie. external interrupts), it could be
anything... EE -> network rx -> SIGIO, or you get out of EE, hit the
softirq path, figure out there was something there waiting processing
(ie, some tty task) and that results in a signal being sent...
> So we have 4 actual exceptions:
> * CriticalInput (some external device signaled this. There are two
> concepts of critical. One is error the other is high priority)
> However this would have the same caveats as any ExternalInput handler.
No, it's worse. It can interrupt code that normally has
local_irq_disabled() and thus doesn't expect to be interrupted. That
means that everything becomes unsafe including locks etc....
Note that driver that want to make active use of that probably want some
explicit local_crit_irq_disable/enable functions to be able to implement
some sort of synchronization.
> * Watchdog - pretty severe if this fires.
>
> * Debug - user space debug is pretty straight forward. However we
> have features like kprobes that require kernel level support.
Which means we have to be extra careful, in fact, I consider it a design
bug of BookE to have made debug be a critical interrupt...
> * MachineCheck - pretty serve if this fires.
>
> So I'm not if there is any good way to preclude the handlers
> associated with these exceptions from doing the things you listed.
Ben.
^ permalink raw reply
* Re: [PATCH 1/2] i2c: Add support for device alias names
From: Jean Delvare @ 2008-05-01 8:04 UTC (permalink / raw)
To: Kay Sievers; +Cc: linuxppc-dev list, Paul Mundt, Scott Wood, Jon, Linux I2C
In-Reply-To: <1209399377.3666.30.camel@linux.site>
Hi Kay,
On Mon, 28 Apr 2008 18:16:17 +0200, Kay Sievers wrote:
> On Mon, 2008-04-28 at 17:40 +0200, Jean Delvare wrote:
> > Why would i2c device modaliases ever contain multiple strings? A device
> > can't have multiple names, can it?
>
> Like ACPI/PNP devices, which can have several compat id's, which means
> that a single device can have "multiple names":
> $ cat /sys/bus/pnp/devices/00:09/id
> IBM0057
> PNP0f13
Ah, I didn't know about this. Now I'm curious how it can work. Does it
mean that several drivers attempt to bind to this device?
> > Adding a ":" at the end of the i2c device names solves the problem I
> > was mentioning, sure, but why don't we simply remove the trailing "*",
> > instead of trying to work around it? A trailing "*" simply makes no
> > sense for aliases which are simple device names.
>
> Sure, if there is only one single string, it's not useful.
>
> > This is not only i2c
> > devices, but also platform devices, acpi, dmi, pnp...
>
> ACPI, DMI, PNP (PNP does not do modalias) needs to be able to match only
> one string in a given list, so the trailing "*" is needed.
OK, I get the idea.
> > Can't we just stop handle_moddevtable() from adding a tailing "*"
> > automatically, and just let the device types which need it, add it on
> > their own?
>
> For a lot subsystems it's fine to have it appended, as there is a
> defined list of identifiers, which must appear in the same order, and
> new identifiers are appended to the end. So the "*" still matches
> modules with possibly extended modalias strings.
I understand the logic, however I am skeptical how useful it is in
practice. If we add an identifier to the device aliases, then we also
update the corresponding modalias, so no in-tree driver can break. The
only case where it makes a difference, as far as I can see, is for
out-of-tree drivers. Am I correct? On top of that, I doubt that we
actually add new identifiers that frequently, do we?
> We would also need to review all buses which export modalias, if they
> need the "*" or not, and add them by hand, if needed.
>
> I guess, it's easier to introduce an additional parameter to
> file2alias::do_table() and suppress the trailing "*" for i2c?
That's one possibility, but I had a slightly different approach, which
is to just let the type-specific handlers add the trailing "*" by
themselves if they need it. This allows for optimization in a few
cases.
Subject: modpost: i2c aliases need no trailing wildcard
Not all device type aliases need a trailing wildcard, in particular
the i2c aliases don't. Don't add a wildcard by default in do_table(),
instead let each device type handler add it if needed.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
---
scripts/mod/file2alias.c | 33 ++++++++++++++++++++++++---------
1 file changed, 24 insertions(+), 9 deletions(-)
--- linux-2.6.26-rc0.orig/scripts/mod/file2alias.c 2008-05-01 07:56:14.000000000 +0200
+++ linux-2.6.26-rc0/scripts/mod/file2alias.c 2008-05-01 09:39:37.000000000 +0200
@@ -51,6 +51,15 @@ do {
sprintf(str + strlen(str), "*"); \
} while(0)
+/* Always end in a wildcard, for future extension */
+static inline void add_wildcard(char *str)
+{
+ int len = strlen(str);
+
+ if (str[len - 1] != '*')
+ strcat(str + len, "*");
+}
+
unsigned int cross_build = 0;
/**
* Check that sizeof(device_id type) are consistent with size of section
@@ -133,9 +142,7 @@ static void do_usb_entry(struct usb_devi
id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
id->bInterfaceProtocol);
- /* Always end in a wildcard, for future extension */
- if (alias[strlen(alias)-1] != '*')
- strcat(alias, "*");
+ add_wildcard(alias);
buf_printf(&mod->dev_table_buf,
"MODULE_ALIAS(\"%s\");\n", alias);
}
@@ -219,6 +226,7 @@ static int do_ieee1394_entry(const char
ADD(alias, "ver", id->match_flags & IEEE1394_MATCH_VERSION,
id->version);
+ add_wildcard(alias);
return 1;
}
@@ -261,6 +269,7 @@ static int do_pci_entry(const char *file
ADD(alias, "bc", baseclass_mask == 0xFF, baseclass);
ADD(alias, "sc", subclass_mask == 0xFF, subclass);
ADD(alias, "i", interface_mask == 0xFF, interface);
+ add_wildcard(alias);
return 1;
}
@@ -283,6 +292,7 @@ static int do_ccw_entry(const char *file
id->dev_type);
ADD(alias, "dm", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
id->dev_model);
+ add_wildcard(alias);
return 1;
}
@@ -290,7 +300,7 @@ static int do_ccw_entry(const char *file
static int do_ap_entry(const char *filename,
struct ap_device_id *id, char *alias)
{
- sprintf(alias, "ap:t%02X", id->dev_type);
+ sprintf(alias, "ap:t%02X*", id->dev_type);
return 1;
}
@@ -309,6 +319,7 @@ static int do_serio_entry(const char *fi
ADD(alias, "id", id->id != SERIO_ANY, id->id);
ADD(alias, "ex", id->extra != SERIO_ANY, id->extra);
+ add_wildcard(alias);
return 1;
}
@@ -316,7 +327,7 @@ static int do_serio_entry(const char *fi
static int do_acpi_entry(const char *filename,
struct acpi_device_id *id, char *alias)
{
- sprintf(alias, "acpi*:%s:", id->id);
+ sprintf(alias, "acpi*:%s:*", id->id);
return 1;
}
@@ -324,7 +335,7 @@ static int do_acpi_entry(const char *fil
static int do_pnp_entry(const char *filename,
struct pnp_device_id *id, char *alias)
{
- sprintf(alias, "pnp:d%s", id->id);
+ sprintf(alias, "pnp:d%s*", id->id);
return 1;
}
@@ -409,6 +420,7 @@ static int do_pcmcia_entry(const char *f
ADD(alias, "pc", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, id->prod_id_hash[2]);
ADD(alias, "pd", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, id->prod_id_hash[3]);
+ add_wildcard(alias);
return 1;
}
@@ -432,6 +444,7 @@ static int do_of_entry (const char *file
if (isspace (*tmp))
*tmp = '_';
+ add_wildcard(alias);
return 1;
}
@@ -448,6 +461,7 @@ static int do_vio_entry(const char *file
if (isspace (*tmp))
*tmp = '_';
+ add_wildcard(alias);
return 1;
}
@@ -529,6 +543,7 @@ static int do_parisc_entry(const char *f
ADD(alias, "rev", id->hversion_rev != PA_HVERSION_REV_ANY_ID, id->hversion_rev);
ADD(alias, "sv", id->sversion != PA_SVERSION_ANY_ID, id->sversion);
+ add_wildcard(alias);
return 1;
}
@@ -544,6 +559,7 @@ static int do_sdio_entry(const char *fil
ADD(alias, "c", id->class != (__u8)SDIO_ANY_ID, id->class);
ADD(alias, "v", id->vendor != (__u16)SDIO_ANY_ID, id->vendor);
ADD(alias, "d", id->device != (__u16)SDIO_ANY_ID, id->device);
+ add_wildcard(alias);
return 1;
}
@@ -559,6 +575,7 @@ static int do_ssb_entry(const char *file
ADD(alias, "v", id->vendor != SSB_ANY_VENDOR, id->vendor);
ADD(alias, "id", id->coreid != SSB_ANY_ID, id->coreid);
ADD(alias, "rev", id->revision != SSB_ANY_REV, id->revision);
+ add_wildcard(alias);
return 1;
}
@@ -573,6 +590,7 @@ static int do_virtio_entry(const char *f
ADD(alias, "d", 1, id->device);
ADD(alias, "v", id->vendor != VIRTIO_DEV_ANY_ID, id->vendor);
+ add_wildcard(alias);
return 1;
}
@@ -612,9 +630,6 @@ static void do_table(void *symval, unsig
for (i = 0; i < size; i += id_size) {
if (do_entry(mod->name, symval+i, alias)) {
- /* Always end in a wildcard, for future extension */
- if (alias[strlen(alias)-1] != '*')
- strcat(alias, "*");
buf_printf(&mod->dev_table_buf,
"MODULE_ALIAS(\"%s\");\n", alias);
}
The patch only changes the i2c aliases, all the rest is the same as
before (unless I messed up somewhere, that is.) Do you think this would
be acceptable for upstream? If you think it's better to add a parameter
to do_table() and let it add the "*" as it did so far, that's also fine
with me, I can update the patch to do that.
Thanks,
--
Jean Delvare
^ permalink raw reply
* Re: [PATCH] [POWERPC] Rework EXC_LEVEL_EXCEPTION_PROLOG code
From: Paul Mackerras @ 2008-05-01 8:24 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <A9B566F7-D00B-4202-9B85-427C38EE6070@kernel.crashing.org>
Kumar Gala writes:
> > It depends on whether a critical or machine check handler can ever do
> > anything to generate a signal or a reschedule. If they can't, then
> > there is no problem.
>
> They can if the come from user space. I'm question what it means to
> send a signal based on receiving an async exception.
The most common cases are (a) something that ultimately generates
input on a tty (e.g. a character arriving on a serial port) and that
input turns out to be a ^C or similar, or (b) something that signals
I/O completion and the program doing the I/O has requested
notification by a SIGIO. But in general any driver code can send a
signal to userspace if it wants.
> > If they can, then we have to be very careful. If a critical or
> > machine check happens at a point where normal interrupts are disabled
> > then we have to be extremely careful not to do anything that the code
> > we've interrupted assumes can't happen - so we'd better not try to
> > take any spinlocks, for example. That severely limits what the
> > handler can do. It probably shouldn't even call printk, for
> > instance, or wake any process up, and definitely shouldn't call
> > schedule (or schedule_preempt) on the way out.
>
> how do we provide someone stick a kprobe on such code today?
-ENOPARSE
> So I'm not if there is any good way to preclude the handlers
> associated with these exceptions from doing the things you listed.
In that case, you'd better expect to see system freezes, memory
corruption and general instability.
Paul.
^ 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