* Re: MPC83xx watchdog reset board dead lock
From: Norbert van Bolhuis @ 2009-06-17 12:16 UTC (permalink / raw)
To: Leon Woestenberg; +Cc: Linux PPC
In-Reply-To: <c384c5ea0906170309j6fdf28f5qc38129e82649ef28@mail.gmail.com>
Hi Leon,
...
> Most designs do not care about the watchdog, or only pet in their
> non-critical paths... That's not what the watchdog is for.
> Also, I don't care about u-boot.
>
> I care about a design where the Flash NOR could be in write mode at
> any time when the watchdog triggers, when the hardware is running
> critical software.
> No lifes in danger when it happens, only jobs, so no biggy :-)
>
true, I was just looking from SW/u-boot perspective.
Ideally the dead-lock is prevented on board/HW level.
>
> David has been helpful in thinking this through, but we followed-up
> offline, and we independently came up with the following design, so
> this must therefore work (disclaimer applies).
>
> Note, it DOES require a NOR flash that has a RY/BUSY# pin.
>
> Quoting David Hawkins, who gave a very clear explanation:
> ---
> How about using the RDY/BUSY# pin on the Flash in conjunction
> with PORESET#. If the flash is busy, then the processor gets
> PORESET#, otherwise, the HRESET# just does its normal thing.
>
> That way PORESET# only ever asserts when you have the
> combo of the Flash being busy and HRESET# asserting.
>
> <...>
>
> If you have the Flash BUSY# signal, then this scheme works
> great, since using HRESET# low and BUSY# low to create a
> PORESET# source is only active until the Flash RESET#
> is asserted long enough for it to get out of the BUSY#
> state and back into read-array mode.
> ---
>
> Kudos to David.
>
> I'll be testing the design tomorrow on the reference board, I'll
> report results in this thread.
>
Interesting.
Looking forward to the results.
---
N. van Bolhuis.
^ permalink raw reply
* Re: [PATCH] Do not inline putprops function
From: Simon Horman @ 2009-06-17 11:45 UTC (permalink / raw)
To: M. Mohan Kumar; +Cc: linuxppc-dev, kexec, miltonm
In-Reply-To: <20090617113456.GC31595@in.ibm.com>
On Wed, Jun 17, 2009 at 05:04:56PM +0530, M. Mohan Kumar wrote:
> Do not inline putprops function
>
> With the recent kexec-tools git tree, both kexec and kdump kernels hang (i.e
> kexec -l and kexec -p respectively). This happened after the patch "ppc64:
> cleanups" commit b43a84a31a4be6ed025c1bdef3bb1c3c12e01b16. I tried
> reverting each hunk and then found out that retaining following lines in
> fs2dt.c makes kexec/kdump work.
>
> -static unsigned *dt_len; /* changed len of modified cmdline
> - in flat device-tree */
>
> [....]
>
> - dt_len = dt;
>
> I don't have any clue why removing a unused variable would cause the kexec
> kernel to hang. After further investigation, I observed that if the putprops
> function is not inlined, kexec/kdump kernel would work even after removing
> the above lines.
>
> This patch directs gcc to not inline the putprops function. Now we could
> invoke kexec and kdump kernels.
I'm happy to apply this if you provide a sign-off,
but do you know why not inlining makes a difference here?
> ---
> kexec/arch/ppc64/fs2dt.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c
> index 1f551fd..1e01f74 100644
> --- a/kexec/arch/ppc64/fs2dt.c
> +++ b/kexec/arch/ppc64/fs2dt.c
> @@ -259,7 +259,7 @@ static void add_usable_mem_property(int fd, int len)
> }
>
> /* put all properties (files) in the property structure */
> -static void putprops(char *fn, struct dirent **nlist, int numlist)
> +__attribute__ ((noinline)) static void putprops(char *fn, struct dirent **nlist, int numlist)
> {
> struct dirent *dp;
> int i = 0, fd, len;
> --
> 1.6.0.6
^ permalink raw reply
* Re: [PATCH 6/6] perf_counter: tools: Makefile tweaks for 64-bit powerpc
From: Ingo Molnar @ 2009-06-17 12:08 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Peter Zijlstra, linux-kernel
In-Reply-To: <19000.55666.866148.559620@cargo.ozlabs.ibm.com>
* Paul Mackerras <paulus@samba.org> wrote:
> +++ b/tools/perf/Makefile
> @@ -157,9 +157,21 @@ uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
> uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
> uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
>
> +# If we're on a 64-bit kernel, use -m64
> +ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
> + M64 := -m64
> +endif
this is fine.
> +# Don't use -Werror on ppc64; we get warnings due to using
> +# %Lx formats on __u64, which is unsigned long.
> +Werror := -Werror
> +ifeq ($(uname_M),ppc64)
> + Werror :=
> +endif
hm, i dont really like this one - it just adds a special case on an
arch. Why is __u64 unsigned long on powerpc and not unsigned long
long? I thought the whole mess with u64 was fixed there recently and
powerpc too now uses include/asm-generic/int-ll64.h ?
ah, it does this:
/*
* This is here because we used to use l64 for 64bit powerpc
* and we don't want to impact user mode with our change to ll64
* in the kernel.
*/
#if defined(__powerpc64__) && !defined(__KERNEL__)
# include <asm-generic/int-l64.h>
#else
# include <asm-generic/int-ll64.h>
#endif
That's crappy really.
Ingo
^ permalink raw reply
* Re: [PATCH 1/6] perf_counter: powerpc: Enable use of software counters on 32-bit powerpc
From: Ingo Molnar @ 2009-06-17 12:04 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Peter Zijlstra, linux-kernel
In-Reply-To: <19000.55404.103840.393470@cargo.ozlabs.ibm.com>
* Paul Mackerras <paulus@samba.org> wrote:
> This depends on the generic atomic64_t patches, which are now in
> Linus' tree. Ingo, if you're putting these in, please pull Linus'
> tree in first.
yes, i already did that earlier today - so all should be fine with
the lib/atomic64.c dependency.
Ingo
^ permalink raw reply
* [PATCH] Do not inline putprops function
From: M. Mohan Kumar @ 2009-06-17 11:59 UTC (permalink / raw)
To: Simon Horman; +Cc: linuxppc-dev, kexec, miltonm
In-Reply-To: <20090617114551.GA5672@verge.net.au>
Do not inline putprops function
With the recent kexec-tools git tree, both kexec and kdump kernels hang (i.e
kexec -l and kexec -p respectively). This happened after the patch "ppc64:
cleanups" commit b43a84a31a4be6ed025c1bdef3bb1c3c12e01b16. I tried
reverting each hunk and then found out that retaining following lines in
fs2dt.c makes kexec/kdump work.
-static unsigned *dt_len; /* changed len of modified cmdline
- in flat device-tree */
[....]
- dt_len = dt;
I don't have any clue why removing a unused variable would cause the kexec
kernel to hang. After further investigation, I observed that if the putprops
function is not inlined, kexec/kdump kernel would work even after removing
the above lines.
This patch directs gcc to not inline the putprops function. Now we could
invoke kexec and kdump kernels.
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
kexec/arch/ppc64/fs2dt.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c
index 1f551fd..1e01f74 100644
--- a/kexec/arch/ppc64/fs2dt.c
+++ b/kexec/arch/ppc64/fs2dt.c
@@ -259,7 +259,7 @@ static void add_usable_mem_property(int fd, int len)
}
/* put all properties (files) in the property structure */
-static void putprops(char *fn, struct dirent **nlist, int numlist)
+__attribute__ ((noinline)) static void putprops(char *fn, struct dirent **nlist, int numlist)
{
struct dirent *dp;
int i = 0, fd, len;
--
1.6.0.6
^ permalink raw reply related
* [PATCH 2/6] perf_counter: powerpc: Use unsigned long for register and constraint values
From: Paul Mackerras @ 2009-06-17 11:51 UTC (permalink / raw)
To: Ingo Molnar, benh; +Cc: linuxppc-dev, Peter Zijlstra, linux-kernel
In-Reply-To: <19000.55404.103840.393470@cargo.ozlabs.ibm.com>
This changes the powerpc perf_counter back-end to use unsigned long
types for hardware register values and for the value/mask pairs used
in checking whether a given set of events fit within the hardware
constraints. This is in preparation for adding support for the PMU
on some 32-bit powerpc processors. On 32-bit processors the hardware
registers are only 32 bits wide, and the PMU structure is generally
simpler, so 32 bits should be ample for expressing the hardware
constraints. On 64-bit processors, unsigned long is 64 bits wide,
so using unsigned long vs. u64 (unsigned long long) makes no actual
difference.
This makes some other very minor changes: adjusting whitespace to line
things up in initialized structures, and simplifying some code in
hw_perf_disable().
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
arch/powerpc/include/asm/perf_counter.h | 35 +++++++------
arch/powerpc/kernel/perf_counter.c | 20 +++----
arch/powerpc/kernel/power4-pmu.c | 74 ++++++++++++++-------------
arch/powerpc/kernel/power5+-pmu.c | 79 +++++++++++++++--------------
arch/powerpc/kernel/power5-pmu.c | 83 ++++++++++++++++---------------
arch/powerpc/kernel/power6-pmu.c | 57 +++++++++++----------
arch/powerpc/kernel/power7-pmu.c | 46 +++++++++--------
arch/powerpc/kernel/ppc970-pmu.c | 47 +++++++++--------
8 files changed, 229 insertions(+), 212 deletions(-)
diff --git a/arch/powerpc/include/asm/perf_counter.h b/arch/powerpc/include/asm/perf_counter.h
index 2c2d9f6..2ceb0fe 100644
--- a/arch/powerpc/include/asm/perf_counter.h
+++ b/arch/powerpc/include/asm/perf_counter.h
@@ -21,21 +21,22 @@
* describe the PMU on a particular POWER-family CPU.
*/
struct power_pmu {
- int n_counter;
- int max_alternatives;
- u64 add_fields;
- u64 test_adder;
- int (*compute_mmcr)(u64 events[], int n_ev,
- unsigned int hwc[], u64 mmcr[]);
- int (*get_constraint)(u64 event, u64 *mskp, u64 *valp);
- int (*get_alternatives)(u64 event, unsigned int flags,
- u64 alt[]);
- void (*disable_pmc)(unsigned int pmc, u64 mmcr[]);
- int (*limited_pmc_event)(u64 event);
- u32 flags;
- int n_generic;
- int *generic_events;
- int (*cache_events)[PERF_COUNT_HW_CACHE_MAX]
+ int n_counter;
+ int max_alternatives;
+ unsigned long add_fields;
+ unsigned long test_adder;
+ int (*compute_mmcr)(u64 events[], int n_ev,
+ unsigned int hwc[], unsigned long mmcr[]);
+ int (*get_constraint)(u64 event, unsigned long *mskp,
+ unsigned long *valp);
+ int (*get_alternatives)(u64 event, unsigned int flags,
+ u64 alt[]);
+ void (*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
+ int (*limited_pmc_event)(u64 event);
+ u32 flags;
+ int n_generic;
+ int *generic_events;
+ int (*cache_events)[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX];
};
@@ -68,8 +69,8 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
#endif
/*
- * The power_pmu.get_constraint function returns a 64-bit value and
- * a 64-bit mask that express the constraints between this event and
+ * The power_pmu.get_constraint function returns a 32/64-bit value and
+ * a 32/64-bit mask that express the constraints between this event and
* other events.
*
* The value and mask are divided up into (non-overlapping) bitfields
diff --git a/arch/powerpc/kernel/perf_counter.c b/arch/powerpc/kernel/perf_counter.c
index e6dc185..0249252 100644
--- a/arch/powerpc/kernel/perf_counter.c
+++ b/arch/powerpc/kernel/perf_counter.c
@@ -29,7 +29,7 @@ struct cpu_hw_counters {
struct perf_counter *counter[MAX_HWCOUNTERS];
u64 events[MAX_HWCOUNTERS];
unsigned int flags[MAX_HWCOUNTERS];
- u64 mmcr[3];
+ unsigned long mmcr[3];
struct perf_counter *limited_counter[MAX_LIMITED_HWCOUNTERS];
u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS];
};
@@ -135,15 +135,15 @@ static void write_pmc(int idx, unsigned long val)
static int power_check_constraints(u64 event[], unsigned int cflags[],
int n_ev)
{
- u64 mask, value, nv;
+ unsigned long mask, value, nv;
u64 alternatives[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
- u64 amasks[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
- u64 avalues[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
- u64 smasks[MAX_HWCOUNTERS], svalues[MAX_HWCOUNTERS];
+ unsigned long amasks[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
+ unsigned long avalues[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
+ unsigned long smasks[MAX_HWCOUNTERS], svalues[MAX_HWCOUNTERS];
int n_alt[MAX_HWCOUNTERS], choice[MAX_HWCOUNTERS];
int i, j;
- u64 addf = ppmu->add_fields;
- u64 tadd = ppmu->test_adder;
+ unsigned long addf = ppmu->add_fields;
+ unsigned long tadd = ppmu->test_adder;
if (n_ev > ppmu->n_counter)
return -1;
@@ -403,14 +403,12 @@ static void write_mmcr0(struct cpu_hw_counters *cpuhw, unsigned long mmcr0)
void hw_perf_disable(void)
{
struct cpu_hw_counters *cpuhw;
- unsigned long ret;
unsigned long flags;
local_irq_save(flags);
cpuhw = &__get_cpu_var(cpu_hw_counters);
- ret = cpuhw->disabled;
- if (!ret) {
+ if (!cpuhw->disabled) {
cpuhw->disabled = 1;
cpuhw->n_added = 0;
@@ -1015,7 +1013,7 @@ static void record_and_restart(struct perf_counter *counter, long val,
u64 period = counter->hw.sample_period;
s64 prev, delta, left;
int record = 0;
- u64 mmcra, sdsync;
+ unsigned long mmcra, sdsync;
/* we don't have to worry about interrupts here */
prev = atomic64_read(&counter->hw.prev_count);
diff --git a/arch/powerpc/kernel/power4-pmu.c b/arch/powerpc/kernel/power4-pmu.c
index 07bd308..81a1708 100644
--- a/arch/powerpc/kernel/power4-pmu.c
+++ b/arch/powerpc/kernel/power4-pmu.c
@@ -179,22 +179,22 @@ static short mmcr1_adder_bits[8] = {
*/
static struct unitinfo {
- u64 value, mask;
- int unit;
- int lowerbit;
+ unsigned long value, mask;
+ int unit;
+ int lowerbit;
} p4_unitinfo[16] = {
- [PM_FPU] = { 0x44000000000000ull, 0x88000000000000ull, PM_FPU, 0 },
- [PM_ISU1] = { 0x20080000000000ull, 0x88000000000000ull, PM_ISU1, 0 },
+ [PM_FPU] = { 0x44000000000000ul, 0x88000000000000ul, PM_FPU, 0 },
+ [PM_ISU1] = { 0x20080000000000ul, 0x88000000000000ul, PM_ISU1, 0 },
[PM_ISU1_ALT] =
- { 0x20080000000000ull, 0x88000000000000ull, PM_ISU1, 0 },
- [PM_IFU] = { 0x02200000000000ull, 0x08820000000000ull, PM_IFU, 41 },
+ { 0x20080000000000ul, 0x88000000000000ul, PM_ISU1, 0 },
+ [PM_IFU] = { 0x02200000000000ul, 0x08820000000000ul, PM_IFU, 41 },
[PM_IFU_ALT] =
- { 0x02200000000000ull, 0x08820000000000ull, PM_IFU, 41 },
- [PM_IDU0] = { 0x10100000000000ull, 0x80840000000000ull, PM_IDU0, 1 },
- [PM_ISU2] = { 0x10140000000000ull, 0x80840000000000ull, PM_ISU2, 0 },
- [PM_LSU0] = { 0x01400000000000ull, 0x08800000000000ull, PM_LSU0, 0 },
- [PM_LSU1] = { 0x00000000000000ull, 0x00010000000000ull, PM_LSU1, 40 },
- [PM_GPS] = { 0x00000000000000ull, 0x00000000000000ull, PM_GPS, 0 }
+ { 0x02200000000000ul, 0x08820000000000ul, PM_IFU, 41 },
+ [PM_IDU0] = { 0x10100000000000ul, 0x80840000000000ul, PM_IDU0, 1 },
+ [PM_ISU2] = { 0x10140000000000ul, 0x80840000000000ul, PM_ISU2, 0 },
+ [PM_LSU0] = { 0x01400000000000ul, 0x08800000000000ul, PM_LSU0, 0 },
+ [PM_LSU1] = { 0x00000000000000ul, 0x00010000000000ul, PM_LSU1, 40 },
+ [PM_GPS] = { 0x00000000000000ul, 0x00000000000000ul, PM_GPS, 0 }
};
static unsigned char direct_marked_event[8] = {
@@ -249,10 +249,11 @@ static int p4_marked_instr_event(u64 event)
return (mask >> (byte * 8 + bit)) & 1;
}
-static int p4_get_constraint(u64 event, u64 *maskp, u64 *valp)
+static int p4_get_constraint(u64 event, unsigned long *maskp,
+ unsigned long *valp)
{
int pmc, byte, unit, lower, sh;
- u64 mask = 0, value = 0;
+ unsigned long mask = 0, value = 0;
int grp = -1;
pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
@@ -282,14 +283,14 @@ static int p4_get_constraint(u64 event, u64 *maskp, u64 *valp)
value |= p4_unitinfo[unit].value;
sh = p4_unitinfo[unit].lowerbit;
if (sh > 1)
- value |= (u64)lower << sh;
+ value |= (unsigned long)lower << sh;
else if (lower != sh)
return -1;
unit = p4_unitinfo[unit].unit;
/* Set byte lane select field */
mask |= 0xfULL << (28 - 4 * byte);
- value |= (u64)unit << (28 - 4 * byte);
+ value |= (unsigned long)unit << (28 - 4 * byte);
}
if (grp == 0) {
/* increment PMC1/2/5/6 field */
@@ -353,9 +354,9 @@ static int p4_get_alternatives(u64 event, unsigned int flags, u64 alt[])
}
static int p4_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], u64 mmcr[])
+ unsigned int hwc[], unsigned long mmcr[])
{
- u64 mmcr0 = 0, mmcr1 = 0, mmcra = 0;
+ unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0;
unsigned int pmc, unit, byte, psel, lower;
unsigned int ttm, grp;
unsigned int pmc_inuse = 0;
@@ -429,9 +430,11 @@ static int p4_compute_mmcr(u64 event[], int n_ev,
return -1;
/* Set TTMxSEL fields. Note, units 1-3 => TTM0SEL codes 0-2 */
- mmcr1 |= (u64)(unituse[3] * 2 + unituse[2]) << MMCR1_TTM0SEL_SH;
- mmcr1 |= (u64)(unituse[7] * 3 + unituse[6] * 2) << MMCR1_TTM1SEL_SH;
- mmcr1 |= (u64)unituse[9] << MMCR1_TTM2SEL_SH;
+ mmcr1 |= (unsigned long)(unituse[3] * 2 + unituse[2])
+ << MMCR1_TTM0SEL_SH;
+ mmcr1 |= (unsigned long)(unituse[7] * 3 + unituse[6] * 2)
+ << MMCR1_TTM1SEL_SH;
+ mmcr1 |= (unsigned long)unituse[9] << MMCR1_TTM2SEL_SH;
/* Set TTCxSEL fields. */
if (unitlower & 0xe)
@@ -456,7 +459,8 @@ static int p4_compute_mmcr(u64 event[], int n_ev,
ttm = unit - 1; /* 2->1, 3->2 */
else
ttm = unit >> 2;
- mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2*byte);
+ mmcr1 |= (unsigned long)ttm
+ << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
}
}
@@ -519,7 +523,7 @@ static int p4_compute_mmcr(u64 event[], int n_ev,
return 0;
}
-static void p4_disable_pmc(unsigned int pmc, u64 mmcr[])
+static void p4_disable_pmc(unsigned int pmc, unsigned long mmcr[])
{
/*
* Setting the PMCxSEL field to 0 disables PMC x.
@@ -584,15 +588,15 @@ static int power4_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
};
struct power_pmu power4_pmu = {
- .n_counter = 8,
- .max_alternatives = 5,
- .add_fields = 0x0000001100005555ull,
- .test_adder = 0x0011083300000000ull,
- .compute_mmcr = p4_compute_mmcr,
- .get_constraint = p4_get_constraint,
- .get_alternatives = p4_get_alternatives,
- .disable_pmc = p4_disable_pmc,
- .n_generic = ARRAY_SIZE(p4_generic_events),
- .generic_events = p4_generic_events,
- .cache_events = &power4_cache_events,
+ .n_counter = 8,
+ .max_alternatives = 5,
+ .add_fields = 0x0000001100005555ul,
+ .test_adder = 0x0011083300000000ul,
+ .compute_mmcr = p4_compute_mmcr,
+ .get_constraint = p4_get_constraint,
+ .get_alternatives = p4_get_alternatives,
+ .disable_pmc = p4_disable_pmc,
+ .n_generic = ARRAY_SIZE(p4_generic_events),
+ .generic_events = p4_generic_events,
+ .cache_events = &power4_cache_events,
};
diff --git a/arch/powerpc/kernel/power5+-pmu.c b/arch/powerpc/kernel/power5+-pmu.c
index 41e5d2d..aef144d 100644
--- a/arch/powerpc/kernel/power5+-pmu.c
+++ b/arch/powerpc/kernel/power5+-pmu.c
@@ -126,20 +126,21 @@ static const int grsel_shift[8] = {
};
/* Masks and values for using events from the various units */
-static u64 unit_cons[PM_LASTUNIT+1][2] = {
- [PM_FPU] = { 0x3200000000ull, 0x0100000000ull },
- [PM_ISU0] = { 0x0200000000ull, 0x0080000000ull },
- [PM_ISU1] = { 0x3200000000ull, 0x3100000000ull },
- [PM_IFU] = { 0x3200000000ull, 0x2100000000ull },
- [PM_IDU] = { 0x0e00000000ull, 0x0040000000ull },
- [PM_GRS] = { 0x0e00000000ull, 0x0c40000000ull },
+static unsigned long unit_cons[PM_LASTUNIT+1][2] = {
+ [PM_FPU] = { 0x3200000000ul, 0x0100000000ul },
+ [PM_ISU0] = { 0x0200000000ul, 0x0080000000ul },
+ [PM_ISU1] = { 0x3200000000ul, 0x3100000000ul },
+ [PM_IFU] = { 0x3200000000ul, 0x2100000000ul },
+ [PM_IDU] = { 0x0e00000000ul, 0x0040000000ul },
+ [PM_GRS] = { 0x0e00000000ul, 0x0c40000000ul },
};
-static int power5p_get_constraint(u64 event, u64 *maskp, u64 *valp)
+static int power5p_get_constraint(u64 event, unsigned long *maskp,
+ unsigned long *valp)
{
int pmc, byte, unit, sh;
int bit, fmask;
- u64 mask = 0, value = 0;
+ unsigned long mask = 0, value = 0;
pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
if (pmc) {
@@ -171,17 +172,18 @@ static int power5p_get_constraint(u64 event, u64 *maskp, u64 *valp)
bit = event & 7;
fmask = (bit == 6)? 7: 3;
sh = grsel_shift[bit];
- mask |= (u64)fmask << sh;
- value |= (u64)((event >> PM_GRS_SH) & fmask) << sh;
+ mask |= (unsigned long)fmask << sh;
+ value |= (unsigned long)((event >> PM_GRS_SH) & fmask)
+ << sh;
}
/* Set byte lane select field */
- mask |= 0xfULL << (24 - 4 * byte);
- value |= (u64)unit << (24 - 4 * byte);
+ mask |= 0xfUL << (24 - 4 * byte);
+ value |= (unsigned long)unit << (24 - 4 * byte);
}
if (pmc < 5) {
/* need a counter from PMC1-4 set */
- mask |= 0x8000000000000ull;
- value |= 0x1000000000000ull;
+ mask |= 0x8000000000000ul;
+ value |= 0x1000000000000ul;
}
*maskp = mask;
*valp = value;
@@ -452,10 +454,10 @@ static int power5p_marked_instr_event(u64 event)
}
static int power5p_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], u64 mmcr[])
+ unsigned int hwc[], unsigned long mmcr[])
{
- u64 mmcr1 = 0;
- u64 mmcra = 0;
+ unsigned long mmcr1 = 0;
+ unsigned long mmcra = 0;
unsigned int pmc, unit, byte, psel;
unsigned int ttm;
int i, isbus, bit, grsel;
@@ -517,7 +519,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev,
continue;
if (ttmuse++)
return -1;
- mmcr1 |= (u64)i << MMCR1_TTM0SEL_SH;
+ mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH;
}
ttmuse = 0;
for (; i <= PM_GRS; ++i) {
@@ -525,7 +527,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev,
continue;
if (ttmuse++)
return -1;
- mmcr1 |= (u64)(i & 3) << MMCR1_TTM1SEL_SH;
+ mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH;
}
if (ttmuse > 1)
return -1;
@@ -540,10 +542,11 @@ static int power5p_compute_mmcr(u64 event[], int n_ev,
unit = PM_ISU0_ALT;
} else if (unit == PM_LSU1 + 1) {
/* select lower word of LSU1 for this byte */
- mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte);
+ mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte);
}
ttm = unit >> 2;
- mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
+ mmcr1 |= (unsigned long)ttm
+ << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
}
/* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */
@@ -568,7 +571,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev,
if (isbus && (byte & 2) &&
(psel == 8 || psel == 0x10 || psel == 0x28))
/* add events on higher-numbered bus */
- mmcr1 |= 1ull << (MMCR1_PMC1_ADDER_SEL_SH - pmc);
+ mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc);
} else {
/* Instructions or run cycles on PMC5/6 */
--pmc;
@@ -576,7 +579,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev,
if (isbus && unit == PM_GRS) {
bit = psel & 7;
grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK;
- mmcr1 |= (u64)grsel << grsel_shift[bit];
+ mmcr1 |= (unsigned long)grsel << grsel_shift[bit];
}
if (power5p_marked_instr_event(event[i]))
mmcra |= MMCRA_SAMPLE_ENABLE;
@@ -599,7 +602,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev,
return 0;
}
-static void power5p_disable_pmc(unsigned int pmc, u64 mmcr[])
+static void power5p_disable_pmc(unsigned int pmc, unsigned long mmcr[])
{
if (pmc <= 3)
mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc));
@@ -655,17 +658,17 @@ static int power5p_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
};
struct power_pmu power5p_pmu = {
- .n_counter = 6,
- .max_alternatives = MAX_ALT,
- .add_fields = 0x7000000000055ull,
- .test_adder = 0x3000040000000ull,
- .compute_mmcr = power5p_compute_mmcr,
- .get_constraint = power5p_get_constraint,
- .get_alternatives = power5p_get_alternatives,
- .disable_pmc = power5p_disable_pmc,
- .limited_pmc_event = power5p_limited_pmc_event,
- .flags = PPMU_LIMITED_PMC5_6,
- .n_generic = ARRAY_SIZE(power5p_generic_events),
- .generic_events = power5p_generic_events,
- .cache_events = &power5p_cache_events,
+ .n_counter = 6,
+ .max_alternatives = MAX_ALT,
+ .add_fields = 0x7000000000055ul,
+ .test_adder = 0x3000040000000ul,
+ .compute_mmcr = power5p_compute_mmcr,
+ .get_constraint = power5p_get_constraint,
+ .get_alternatives = power5p_get_alternatives,
+ .disable_pmc = power5p_disable_pmc,
+ .limited_pmc_event = power5p_limited_pmc_event,
+ .flags = PPMU_LIMITED_PMC5_6,
+ .n_generic = ARRAY_SIZE(power5p_generic_events),
+ .generic_events = power5p_generic_events,
+ .cache_events = &power5p_cache_events,
};
diff --git a/arch/powerpc/kernel/power5-pmu.c b/arch/powerpc/kernel/power5-pmu.c
index 05600b6..8694c73 100644
--- a/arch/powerpc/kernel/power5-pmu.c
+++ b/arch/powerpc/kernel/power5-pmu.c
@@ -130,20 +130,21 @@ static const int grsel_shift[8] = {
};
/* Masks and values for using events from the various units */
-static u64 unit_cons[PM_LASTUNIT+1][2] = {
- [PM_FPU] = { 0xc0002000000000ull, 0x00001000000000ull },
- [PM_ISU0] = { 0x00002000000000ull, 0x00000800000000ull },
- [PM_ISU1] = { 0xc0002000000000ull, 0xc0001000000000ull },
- [PM_IFU] = { 0xc0002000000000ull, 0x80001000000000ull },
- [PM_IDU] = { 0x30002000000000ull, 0x00000400000000ull },
- [PM_GRS] = { 0x30002000000000ull, 0x30000400000000ull },
+static unsigned long unit_cons[PM_LASTUNIT+1][2] = {
+ [PM_FPU] = { 0xc0002000000000ul, 0x00001000000000ul },
+ [PM_ISU0] = { 0x00002000000000ul, 0x00000800000000ul },
+ [PM_ISU1] = { 0xc0002000000000ul, 0xc0001000000000ul },
+ [PM_IFU] = { 0xc0002000000000ul, 0x80001000000000ul },
+ [PM_IDU] = { 0x30002000000000ul, 0x00000400000000ul },
+ [PM_GRS] = { 0x30002000000000ul, 0x30000400000000ul },
};
-static int power5_get_constraint(u64 event, u64 *maskp, u64 *valp)
+static int power5_get_constraint(u64 event, unsigned long *maskp,
+ unsigned long *valp)
{
int pmc, byte, unit, sh;
int bit, fmask;
- u64 mask = 0, value = 0;
+ unsigned long mask = 0, value = 0;
int grp = -1;
pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
@@ -178,8 +179,9 @@ static int power5_get_constraint(u64 event, u64 *maskp, u64 *valp)
bit = event & 7;
fmask = (bit == 6)? 7: 3;
sh = grsel_shift[bit];
- mask |= (u64)fmask << sh;
- value |= (u64)((event >> PM_GRS_SH) & fmask) << sh;
+ mask |= (unsigned long)fmask << sh;
+ value |= (unsigned long)((event >> PM_GRS_SH) & fmask)
+ << sh;
}
/*
* Bus events on bytes 0 and 2 can be counted
@@ -188,22 +190,22 @@ static int power5_get_constraint(u64 event, u64 *maskp, u64 *valp)
if (!pmc)
grp = byte & 1;
/* Set byte lane select field */
- mask |= 0xfULL << (24 - 4 * byte);
- value |= (u64)unit << (24 - 4 * byte);
+ mask |= 0xfUL << (24 - 4 * byte);
+ value |= (unsigned long)unit << (24 - 4 * byte);
}
if (grp == 0) {
/* increment PMC1/2 field */
- mask |= 0x200000000ull;
- value |= 0x080000000ull;
+ mask |= 0x200000000ul;
+ value |= 0x080000000ul;
} else if (grp == 1) {
/* increment PMC3/4 field */
- mask |= 0x40000000ull;
- value |= 0x10000000ull;
+ mask |= 0x40000000ul;
+ value |= 0x10000000ul;
}
if (pmc < 5) {
/* need a counter from PMC1-4 set */
- mask |= 0x8000000000000ull;
- value |= 0x1000000000000ull;
+ mask |= 0x8000000000000ul;
+ value |= 0x1000000000000ul;
}
*maskp = mask;
*valp = value;
@@ -383,10 +385,10 @@ static int power5_marked_instr_event(u64 event)
}
static int power5_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], u64 mmcr[])
+ unsigned int hwc[], unsigned long mmcr[])
{
- u64 mmcr1 = 0;
- u64 mmcra = 0;
+ unsigned long mmcr1 = 0;
+ unsigned long mmcra = 0;
unsigned int pmc, unit, byte, psel;
unsigned int ttm, grp;
int i, isbus, bit, grsel;
@@ -457,7 +459,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev,
continue;
if (ttmuse++)
return -1;
- mmcr1 |= (u64)i << MMCR1_TTM0SEL_SH;
+ mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH;
}
ttmuse = 0;
for (; i <= PM_GRS; ++i) {
@@ -465,7 +467,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev,
continue;
if (ttmuse++)
return -1;
- mmcr1 |= (u64)(i & 3) << MMCR1_TTM1SEL_SH;
+ mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH;
}
if (ttmuse > 1)
return -1;
@@ -480,10 +482,11 @@ static int power5_compute_mmcr(u64 event[], int n_ev,
unit = PM_ISU0_ALT;
} else if (unit == PM_LSU1 + 1) {
/* select lower word of LSU1 for this byte */
- mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte);
+ mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte);
}
ttm = unit >> 2;
- mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
+ mmcr1 |= (unsigned long)ttm
+ << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
}
/* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */
@@ -513,7 +516,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev,
--pmc;
if ((psel == 8 || psel == 0x10) && isbus && (byte & 2))
/* add events on higher-numbered bus */
- mmcr1 |= 1ull << (MMCR1_PMC1_ADDER_SEL_SH - pmc);
+ mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc);
} else {
/* Instructions or run cycles on PMC5/6 */
--pmc;
@@ -521,7 +524,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev,
if (isbus && unit == PM_GRS) {
bit = psel & 7;
grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK;
- mmcr1 |= (u64)grsel << grsel_shift[bit];
+ mmcr1 |= (unsigned long)grsel << grsel_shift[bit];
}
if (power5_marked_instr_event(event[i]))
mmcra |= MMCRA_SAMPLE_ENABLE;
@@ -541,7 +544,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev,
return 0;
}
-static void power5_disable_pmc(unsigned int pmc, u64 mmcr[])
+static void power5_disable_pmc(unsigned int pmc, unsigned long mmcr[])
{
if (pmc <= 3)
mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc));
@@ -597,15 +600,15 @@ static int power5_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
};
struct power_pmu power5_pmu = {
- .n_counter = 6,
- .max_alternatives = MAX_ALT,
- .add_fields = 0x7000090000555ull,
- .test_adder = 0x3000490000000ull,
- .compute_mmcr = power5_compute_mmcr,
- .get_constraint = power5_get_constraint,
- .get_alternatives = power5_get_alternatives,
- .disable_pmc = power5_disable_pmc,
- .n_generic = ARRAY_SIZE(power5_generic_events),
- .generic_events = power5_generic_events,
- .cache_events = &power5_cache_events,
+ .n_counter = 6,
+ .max_alternatives = MAX_ALT,
+ .add_fields = 0x7000090000555ul,
+ .test_adder = 0x3000490000000ul,
+ .compute_mmcr = power5_compute_mmcr,
+ .get_constraint = power5_get_constraint,
+ .get_alternatives = power5_get_alternatives,
+ .disable_pmc = power5_disable_pmc,
+ .n_generic = ARRAY_SIZE(power5_generic_events),
+ .generic_events = power5_generic_events,
+ .cache_events = &power5_cache_events,
};
diff --git a/arch/powerpc/kernel/power6-pmu.c b/arch/powerpc/kernel/power6-pmu.c
index 46f74be..8898622 100644
--- a/arch/powerpc/kernel/power6-pmu.c
+++ b/arch/powerpc/kernel/power6-pmu.c
@@ -41,9 +41,9 @@
#define MMCR1_NESTSEL_SH 45
#define MMCR1_NESTSEL_MSK 0x7
#define MMCR1_NESTSEL(m) (((m) >> MMCR1_NESTSEL_SH) & MMCR1_NESTSEL_MSK)
-#define MMCR1_PMC1_LLA ((u64)1 << 44)
-#define MMCR1_PMC1_LLA_VALUE ((u64)1 << 39)
-#define MMCR1_PMC1_ADDR_SEL ((u64)1 << 35)
+#define MMCR1_PMC1_LLA (1ul << 44)
+#define MMCR1_PMC1_LLA_VALUE (1ul << 39)
+#define MMCR1_PMC1_ADDR_SEL (1ul << 35)
#define MMCR1_PMC1SEL_SH 24
#define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8)
#define MMCR1_PMCSEL_MSK 0xff
@@ -173,10 +173,10 @@ static int power6_marked_instr_event(u64 event)
* Assign PMC numbers and compute MMCR1 value for a set of events
*/
static int p6_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], u64 mmcr[])
+ unsigned int hwc[], unsigned long mmcr[])
{
- u64 mmcr1 = 0;
- u64 mmcra = 0;
+ unsigned long mmcr1 = 0;
+ unsigned long mmcra = 0;
int i;
unsigned int pmc, ev, b, u, s, psel;
unsigned int ttmset = 0;
@@ -215,7 +215,7 @@ static int p6_compute_mmcr(u64 event[], int n_ev,
/* check for conflict on this byte of event bus */
if ((ttmset & (1 << b)) && MMCR1_TTMSEL(mmcr1, b) != u)
return -1;
- mmcr1 |= (u64)u << MMCR1_TTMSEL_SH(b);
+ mmcr1 |= (unsigned long)u << MMCR1_TTMSEL_SH(b);
ttmset |= 1 << b;
if (u == 5) {
/* Nest events have a further mux */
@@ -224,7 +224,7 @@ static int p6_compute_mmcr(u64 event[], int n_ev,
MMCR1_NESTSEL(mmcr1) != s)
return -1;
ttmset |= 0x10;
- mmcr1 |= (u64)s << MMCR1_NESTSEL_SH;
+ mmcr1 |= (unsigned long)s << MMCR1_NESTSEL_SH;
}
if (0x30 <= psel && psel <= 0x3d) {
/* these need the PMCx_ADDR_SEL bits */
@@ -243,7 +243,7 @@ static int p6_compute_mmcr(u64 event[], int n_ev,
if (power6_marked_instr_event(event[i]))
mmcra |= MMCRA_SAMPLE_ENABLE;
if (pmc < 4)
- mmcr1 |= (u64)psel << MMCR1_PMCSEL_SH(pmc);
+ mmcr1 |= (unsigned long)psel << MMCR1_PMCSEL_SH(pmc);
}
mmcr[0] = 0;
if (pmc_inuse & 1)
@@ -265,10 +265,11 @@ static int p6_compute_mmcr(u64 event[], int n_ev,
* 20-23, 24-27, 28-31 ditto for bytes 1, 2, 3
* 32-34 select field: nest (subunit) event selector
*/
-static int p6_get_constraint(u64 event, u64 *maskp, u64 *valp)
+static int p6_get_constraint(u64 event, unsigned long *maskp,
+ unsigned long *valp)
{
int pmc, byte, sh, subunit;
- u64 mask = 0, value = 0;
+ unsigned long mask = 0, value = 0;
pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
if (pmc) {
@@ -282,11 +283,11 @@ static int p6_get_constraint(u64 event, u64 *maskp, u64 *valp)
byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
sh = byte * 4 + (16 - PM_UNIT_SH);
mask |= PM_UNIT_MSKS << sh;
- value |= (u64)(event & PM_UNIT_MSKS) << sh;
+ value |= (unsigned long)(event & PM_UNIT_MSKS) << sh;
if ((event & PM_UNIT_MSKS) == (5 << PM_UNIT_SH)) {
subunit = (event >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK;
- mask |= (u64)PM_SUBUNIT_MSK << 32;
- value |= (u64)subunit << 32;
+ mask |= (unsigned long)PM_SUBUNIT_MSK << 32;
+ value |= (unsigned long)subunit << 32;
}
}
if (pmc <= 4) {
@@ -458,7 +459,7 @@ static int p6_get_alternatives(u64 event, unsigned int flags, u64 alt[])
return nalt;
}
-static void p6_disable_pmc(unsigned int pmc, u64 mmcr[])
+static void p6_disable_pmc(unsigned int pmc, unsigned long mmcr[])
{
/* Set PMCxSEL to 0 to disable PMCx */
if (pmc <= 3)
@@ -516,17 +517,17 @@ static int power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
};
struct power_pmu power6_pmu = {
- .n_counter = 6,
- .max_alternatives = MAX_ALT,
- .add_fields = 0x1555,
- .test_adder = 0x3000,
- .compute_mmcr = p6_compute_mmcr,
- .get_constraint = p6_get_constraint,
- .get_alternatives = p6_get_alternatives,
- .disable_pmc = p6_disable_pmc,
- .limited_pmc_event = p6_limited_pmc_event,
- .flags = PPMU_LIMITED_PMC5_6 | PPMU_ALT_SIPR,
- .n_generic = ARRAY_SIZE(power6_generic_events),
- .generic_events = power6_generic_events,
- .cache_events = &power6_cache_events,
+ .n_counter = 6,
+ .max_alternatives = MAX_ALT,
+ .add_fields = 0x1555,
+ .test_adder = 0x3000,
+ .compute_mmcr = p6_compute_mmcr,
+ .get_constraint = p6_get_constraint,
+ .get_alternatives = p6_get_alternatives,
+ .disable_pmc = p6_disable_pmc,
+ .limited_pmc_event = p6_limited_pmc_event,
+ .flags = PPMU_LIMITED_PMC5_6 | PPMU_ALT_SIPR,
+ .n_generic = ARRAY_SIZE(power6_generic_events),
+ .generic_events = power6_generic_events,
+ .cache_events = &power6_cache_events,
};
diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/kernel/power7-pmu.c
index b72e7a1..658d1ae 100644
--- a/arch/powerpc/kernel/power7-pmu.c
+++ b/arch/powerpc/kernel/power7-pmu.c
@@ -71,10 +71,11 @@
* 0-9: Count of events needing PMC1..PMC5
*/
-static int power7_get_constraint(u64 event, u64 *maskp, u64 *valp)
+static int power7_get_constraint(u64 event, unsigned long *maskp,
+ unsigned long *valp)
{
int pmc, sh;
- u64 mask = 0, value = 0;
+ unsigned long mask = 0, value = 0;
pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
if (pmc) {
@@ -224,10 +225,10 @@ static int power7_marked_instr_event(u64 event)
}
static int power7_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], u64 mmcr[])
+ unsigned int hwc[], unsigned long mmcr[])
{
- u64 mmcr1 = 0;
- u64 mmcra = 0;
+ unsigned long mmcr1 = 0;
+ unsigned long mmcra = 0;
unsigned int pmc, unit, combine, l2sel, psel;
unsigned int pmc_inuse = 0;
int i;
@@ -265,11 +266,14 @@ static int power7_compute_mmcr(u64 event[], int n_ev,
--pmc;
}
if (pmc <= 3) {
- mmcr1 |= (u64) unit << (MMCR1_TTM0SEL_SH - 4 * pmc);
- mmcr1 |= (u64) combine << (MMCR1_PMC1_COMBINE_SH - pmc);
+ mmcr1 |= (unsigned long) unit
+ << (MMCR1_TTM0SEL_SH - 4 * pmc);
+ mmcr1 |= (unsigned long) combine
+ << (MMCR1_PMC1_COMBINE_SH - pmc);
mmcr1 |= psel << MMCR1_PMCSEL_SH(pmc);
if (unit == 6) /* L2 events */
- mmcr1 |= (u64) l2sel << MMCR1_L2SEL_SH;
+ mmcr1 |= (unsigned long) l2sel
+ << MMCR1_L2SEL_SH;
}
if (power7_marked_instr_event(event[i]))
mmcra |= MMCRA_SAMPLE_ENABLE;
@@ -287,10 +291,10 @@ static int power7_compute_mmcr(u64 event[], int n_ev,
return 0;
}
-static void power7_disable_pmc(unsigned int pmc, u64 mmcr[])
+static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[])
{
if (pmc <= 3)
- mmcr[1] &= ~(0xffULL << MMCR1_PMCSEL_SH(pmc));
+ mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SH(pmc));
}
static int power7_generic_events[] = {
@@ -343,15 +347,15 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
};
struct power_pmu power7_pmu = {
- .n_counter = 6,
- .max_alternatives = MAX_ALT + 1,
- .add_fields = 0x1555ull,
- .test_adder = 0x3000ull,
- .compute_mmcr = power7_compute_mmcr,
- .get_constraint = power7_get_constraint,
- .get_alternatives = power7_get_alternatives,
- .disable_pmc = power7_disable_pmc,
- .n_generic = ARRAY_SIZE(power7_generic_events),
- .generic_events = power7_generic_events,
- .cache_events = &power7_cache_events,
+ .n_counter = 6,
+ .max_alternatives = MAX_ALT + 1,
+ .add_fields = 0x1555ul,
+ .test_adder = 0x3000ul,
+ .compute_mmcr = power7_compute_mmcr,
+ .get_constraint = power7_get_constraint,
+ .get_alternatives = power7_get_alternatives,
+ .disable_pmc = power7_disable_pmc,
+ .n_generic = ARRAY_SIZE(power7_generic_events),
+ .generic_events = power7_generic_events,
+ .cache_events = &power7_cache_events,
};
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c
index ba0a357..3ed8833 100644
--- a/arch/powerpc/kernel/ppc970-pmu.c
+++ b/arch/powerpc/kernel/ppc970-pmu.c
@@ -183,7 +183,7 @@ static int p970_marked_instr_event(u64 event)
}
/* Masks and values for using events from the various units */
-static u64 unit_cons[PM_LASTUNIT+1][2] = {
+static unsigned long unit_cons[PM_LASTUNIT+1][2] = {
[PM_FPU] = { 0xc80000000000ull, 0x040000000000ull },
[PM_VPU] = { 0xc80000000000ull, 0xc40000000000ull },
[PM_ISU] = { 0x080000000000ull, 0x020000000000ull },
@@ -192,10 +192,11 @@ static u64 unit_cons[PM_LASTUNIT+1][2] = {
[PM_STS] = { 0x380000000000ull, 0x310000000000ull },
};
-static int p970_get_constraint(u64 event, u64 *maskp, u64 *valp)
+static int p970_get_constraint(u64 event, unsigned long *maskp,
+ unsigned long *valp)
{
int pmc, byte, unit, sh, spcsel;
- u64 mask = 0, value = 0;
+ unsigned long mask = 0, value = 0;
int grp = -1;
pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
@@ -222,7 +223,7 @@ static int p970_get_constraint(u64 event, u64 *maskp, u64 *valp)
grp = byte & 1;
/* Set byte lane select field */
mask |= 0xfULL << (28 - 4 * byte);
- value |= (u64)unit << (28 - 4 * byte);
+ value |= (unsigned long)unit << (28 - 4 * byte);
}
if (grp == 0) {
/* increment PMC1/2/5/6 field */
@@ -236,7 +237,7 @@ static int p970_get_constraint(u64 event, u64 *maskp, u64 *valp)
spcsel = (event >> PM_SPCSEL_SH) & PM_SPCSEL_MSK;
if (spcsel) {
mask |= 3ull << 48;
- value |= (u64)spcsel << 48;
+ value |= (unsigned long)spcsel << 48;
}
*maskp = mask;
*valp = value;
@@ -257,9 +258,9 @@ static int p970_get_alternatives(u64 event, unsigned int flags, u64 alt[])
}
static int p970_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], u64 mmcr[])
+ unsigned int hwc[], unsigned long mmcr[])
{
- u64 mmcr0 = 0, mmcr1 = 0, mmcra = 0;
+ unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0;
unsigned int pmc, unit, byte, psel;
unsigned int ttm, grp;
unsigned int pmc_inuse = 0;
@@ -320,7 +321,7 @@ static int p970_compute_mmcr(u64 event[], int n_ev,
continue;
ttm = unitmap[i];
++ttmuse[(ttm >> 2) & 1];
- mmcr1 |= (u64)(ttm & ~4) << MMCR1_TTM1SEL_SH;
+ mmcr1 |= (unsigned long)(ttm & ~4) << MMCR1_TTM1SEL_SH;
}
/* Check only one unit per TTMx */
if (ttmuse[0] > 1 || ttmuse[1] > 1)
@@ -340,7 +341,8 @@ static int p970_compute_mmcr(u64 event[], int n_ev,
if (unit == PM_LSU1L && byte >= 2)
mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte);
}
- mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
+ mmcr1 |= (unsigned long)ttm
+ << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
}
/* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */
@@ -386,7 +388,8 @@ static int p970_compute_mmcr(u64 event[], int n_ev,
for (pmc = 0; pmc < 2; ++pmc)
mmcr0 |= pmcsel[pmc] << (MMCR0_PMC1SEL_SH - 7 * pmc);
for (; pmc < 8; ++pmc)
- mmcr1 |= (u64)pmcsel[pmc] << (MMCR1_PMC3SEL_SH - 5 * (pmc - 2));
+ mmcr1 |= (unsigned long)pmcsel[pmc]
+ << (MMCR1_PMC3SEL_SH - 5 * (pmc - 2));
if (pmc_inuse & 1)
mmcr0 |= MMCR0_PMC1CE;
if (pmc_inuse & 0xfe)
@@ -401,7 +404,7 @@ static int p970_compute_mmcr(u64 event[], int n_ev,
return 0;
}
-static void p970_disable_pmc(unsigned int pmc, u64 mmcr[])
+static void p970_disable_pmc(unsigned int pmc, unsigned long mmcr[])
{
int shift, i;
@@ -468,15 +471,15 @@ static int ppc970_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
};
struct power_pmu ppc970_pmu = {
- .n_counter = 8,
- .max_alternatives = 2,
- .add_fields = 0x001100005555ull,
- .test_adder = 0x013300000000ull,
- .compute_mmcr = p970_compute_mmcr,
- .get_constraint = p970_get_constraint,
- .get_alternatives = p970_get_alternatives,
- .disable_pmc = p970_disable_pmc,
- .n_generic = ARRAY_SIZE(ppc970_generic_events),
- .generic_events = ppc970_generic_events,
- .cache_events = &ppc970_cache_events,
+ .n_counter = 8,
+ .max_alternatives = 2,
+ .add_fields = 0x001100005555ull,
+ .test_adder = 0x013300000000ull,
+ .compute_mmcr = p970_compute_mmcr,
+ .get_constraint = p970_get_constraint,
+ .get_alternatives = p970_get_alternatives,
+ .disable_pmc = p970_disable_pmc,
+ .n_generic = ARRAY_SIZE(ppc970_generic_events),
+ .generic_events = ppc970_generic_events,
+ .cache_events = &ppc970_cache_events,
};
--
1.6.0.4
^ permalink raw reply related
* [PATCH 3/6] perf_counter: powerpc: Change how processor-specific back-ends get selected
From: Paul Mackerras @ 2009-06-17 11:52 UTC (permalink / raw)
To: Ingo Molnar, benh; +Cc: linuxppc-dev, Peter Zijlstra, linux-kernel
In-Reply-To: <19000.55404.103840.393470@cargo.ozlabs.ibm.com>
At present, the powerpc generic (processor-independent) perf_counter
code has list of processor back-end modules, and at initialization,
it looks at the PVR (processor version register) and has a switch
statement to select a suitable processor-specific back-end.
This is going to become inconvenient as we add more processor-specific
back-ends, so this inverts the order: now each back-end checks whether
it applies to the current processor, and registers itself if so.
Furthermore, instead of looking at the PVR, back-ends now check the
cur_cpu_spec->oprofile_cpu_type string and match on that.
Lastly, each back-end now specifies a name for itself so the core can
print a nice message when a back-end registers itself.
This doesn't provide any support for unregistering back-ends, but that
wouldn't be hard to do and would allow back-ends to be modules.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
arch/powerpc/include/asm/perf_counter.h | 5 ++-
arch/powerpc/kernel/perf_counter.c | 44 +++++--------------------------
arch/powerpc/kernel/power4-pmu.c | 15 ++++++++++-
arch/powerpc/kernel/power5+-pmu.c | 16 ++++++++++-
arch/powerpc/kernel/power5-pmu.c | 15 ++++++++++-
arch/powerpc/kernel/power6-pmu.c | 15 ++++++++++-
arch/powerpc/kernel/power7-pmu.c | 15 ++++++++++-
arch/powerpc/kernel/ppc970-pmu.c | 16 ++++++++++-
8 files changed, 96 insertions(+), 45 deletions(-)
diff --git a/arch/powerpc/include/asm/perf_counter.h b/arch/powerpc/include/asm/perf_counter.h
index 2ceb0fe..8ccd4e1 100644
--- a/arch/powerpc/include/asm/perf_counter.h
+++ b/arch/powerpc/include/asm/perf_counter.h
@@ -21,6 +21,7 @@
* describe the PMU on a particular POWER-family CPU.
*/
struct power_pmu {
+ const char *name;
int n_counter;
int max_alternatives;
unsigned long add_fields;
@@ -41,8 +42,6 @@ struct power_pmu {
[PERF_COUNT_HW_CACHE_RESULT_MAX];
};
-extern struct power_pmu *ppmu;
-
/*
* Values for power_pmu.flags
*/
@@ -56,6 +55,8 @@ extern struct power_pmu *ppmu;
#define PPMU_LIMITED_PMC_REQD 2 /* have to put this on a limited PMC */
#define PPMU_ONLY_COUNT_RUN 4 /* only counting in run state */
+extern int register_power_pmu(struct power_pmu *);
+
struct pt_regs;
extern unsigned long perf_misc_flags(struct pt_regs *regs);
extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
diff --git a/arch/powerpc/kernel/perf_counter.c b/arch/powerpc/kernel/perf_counter.c
index 0249252..54e0489 100644
--- a/arch/powerpc/kernel/perf_counter.c
+++ b/arch/powerpc/kernel/perf_counter.c
@@ -1214,42 +1214,14 @@ void hw_perf_counter_setup(int cpu)
cpuhw->mmcr[0] = MMCR0_FC;
}
-extern struct power_pmu power4_pmu;
-extern struct power_pmu ppc970_pmu;
-extern struct power_pmu power5_pmu;
-extern struct power_pmu power5p_pmu;
-extern struct power_pmu power6_pmu;
-extern struct power_pmu power7_pmu;
-
-static int init_perf_counters(void)
+int register_power_pmu(struct power_pmu *pmu)
{
- unsigned long pvr;
-
- /* XXX should get this from cputable */
- pvr = mfspr(SPRN_PVR);
- switch (PVR_VER(pvr)) {
- case PV_POWER4:
- case PV_POWER4p:
- ppmu = &power4_pmu;
- break;
- case PV_970:
- case PV_970FX:
- case PV_970MP:
- ppmu = &ppc970_pmu;
- break;
- case PV_POWER5:
- ppmu = &power5_pmu;
- break;
- case PV_POWER5p:
- ppmu = &power5p_pmu;
- break;
- case 0x3e:
- ppmu = &power6_pmu;
- break;
- case 0x3f:
- ppmu = &power7_pmu;
- break;
- }
+ if (ppmu)
+ return -EBUSY; /* something's already registered */
+
+ ppmu = pmu;
+ pr_info("%s performance monitor hardware support registered\n",
+ pmu->name);
/*
* Use FCHV to ignore kernel events if MSR.HV is set.
@@ -1259,5 +1231,3 @@ static int init_perf_counters(void)
return 0;
}
-
-arch_initcall(init_perf_counters);
diff --git a/arch/powerpc/kernel/power4-pmu.c b/arch/powerpc/kernel/power4-pmu.c
index 81a1708..db90b0c 100644
--- a/arch/powerpc/kernel/power4-pmu.c
+++ b/arch/powerpc/kernel/power4-pmu.c
@@ -10,7 +10,9 @@
*/
#include <linux/kernel.h>
#include <linux/perf_counter.h>
+#include <linux/string.h>
#include <asm/reg.h>
+#include <asm/cputable.h>
/*
* Bits in event code for POWER4
@@ -587,7 +589,8 @@ static int power4_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
},
};
-struct power_pmu power4_pmu = {
+static struct power_pmu power4_pmu = {
+ .name = "POWER4/4+",
.n_counter = 8,
.max_alternatives = 5,
.add_fields = 0x0000001100005555ul,
@@ -600,3 +603,13 @@ struct power_pmu power4_pmu = {
.generic_events = p4_generic_events,
.cache_events = &power4_cache_events,
};
+
+static int init_power4_pmu(void)
+{
+ if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power4"))
+ return -ENODEV;
+
+ return register_power_pmu(&power4_pmu);
+}
+
+arch_initcall(init_power4_pmu);
diff --git a/arch/powerpc/kernel/power5+-pmu.c b/arch/powerpc/kernel/power5+-pmu.c
index aef144d..f4adca8 100644
--- a/arch/powerpc/kernel/power5+-pmu.c
+++ b/arch/powerpc/kernel/power5+-pmu.c
@@ -10,7 +10,9 @@
*/
#include <linux/kernel.h>
#include <linux/perf_counter.h>
+#include <linux/string.h>
#include <asm/reg.h>
+#include <asm/cputable.h>
/*
* Bits in event code for POWER5+ (POWER5 GS) and POWER5++ (POWER5 GS DD3)
@@ -657,7 +659,8 @@ static int power5p_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
},
};
-struct power_pmu power5p_pmu = {
+static struct power_pmu power5p_pmu = {
+ .name = "POWER5+/++",
.n_counter = 6,
.max_alternatives = MAX_ALT,
.add_fields = 0x7000000000055ul,
@@ -672,3 +675,14 @@ struct power_pmu power5p_pmu = {
.generic_events = power5p_generic_events,
.cache_events = &power5p_cache_events,
};
+
+static int init_power5p_pmu(void)
+{
+ if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5+")
+ && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5++"))
+ return -ENODEV;
+
+ return register_power_pmu(&power5p_pmu);
+}
+
+arch_initcall(init_power5p_pmu);
diff --git a/arch/powerpc/kernel/power5-pmu.c b/arch/powerpc/kernel/power5-pmu.c
index 8694c73..29b2c6c 100644
--- a/arch/powerpc/kernel/power5-pmu.c
+++ b/arch/powerpc/kernel/power5-pmu.c
@@ -10,7 +10,9 @@
*/
#include <linux/kernel.h>
#include <linux/perf_counter.h>
+#include <linux/string.h>
#include <asm/reg.h>
+#include <asm/cputable.h>
/*
* Bits in event code for POWER5 (not POWER5++)
@@ -599,7 +601,8 @@ static int power5_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
},
};
-struct power_pmu power5_pmu = {
+static struct power_pmu power5_pmu = {
+ .name = "POWER5",
.n_counter = 6,
.max_alternatives = MAX_ALT,
.add_fields = 0x7000090000555ul,
@@ -612,3 +615,13 @@ struct power_pmu power5_pmu = {
.generic_events = power5_generic_events,
.cache_events = &power5_cache_events,
};
+
+static int init_power5_pmu(void)
+{
+ if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5"))
+ return -ENODEV;
+
+ return register_power_pmu(&power5_pmu);
+}
+
+arch_initcall(init_power5_pmu);
diff --git a/arch/powerpc/kernel/power6-pmu.c b/arch/powerpc/kernel/power6-pmu.c
index 8898622..09ae5bf 100644
--- a/arch/powerpc/kernel/power6-pmu.c
+++ b/arch/powerpc/kernel/power6-pmu.c
@@ -10,7 +10,9 @@
*/
#include <linux/kernel.h>
#include <linux/perf_counter.h>
+#include <linux/string.h>
#include <asm/reg.h>
+#include <asm/cputable.h>
/*
* Bits in event code for POWER6
@@ -516,7 +518,8 @@ static int power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
},
};
-struct power_pmu power6_pmu = {
+static struct power_pmu power6_pmu = {
+ .name = "POWER6",
.n_counter = 6,
.max_alternatives = MAX_ALT,
.add_fields = 0x1555,
@@ -531,3 +534,13 @@ struct power_pmu power6_pmu = {
.generic_events = power6_generic_events,
.cache_events = &power6_cache_events,
};
+
+static int init_power6_pmu(void)
+{
+ if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power6"))
+ return -ENODEV;
+
+ return register_power_pmu(&power6_pmu);
+}
+
+arch_initcall(init_power6_pmu);
diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/kernel/power7-pmu.c
index 658d1ae..5d755ef 100644
--- a/arch/powerpc/kernel/power7-pmu.c
+++ b/arch/powerpc/kernel/power7-pmu.c
@@ -10,7 +10,9 @@
*/
#include <linux/kernel.h>
#include <linux/perf_counter.h>
+#include <linux/string.h>
#include <asm/reg.h>
+#include <asm/cputable.h>
/*
* Bits in event code for POWER7
@@ -346,7 +348,8 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
},
};
-struct power_pmu power7_pmu = {
+static struct power_pmu power7_pmu = {
+ .name = "POWER7",
.n_counter = 6,
.max_alternatives = MAX_ALT + 1,
.add_fields = 0x1555ul,
@@ -359,3 +362,13 @@ struct power_pmu power7_pmu = {
.generic_events = power7_generic_events,
.cache_events = &power7_cache_events,
};
+
+static int init_power7_pmu(void)
+{
+ if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power7"))
+ return -ENODEV;
+
+ return register_power_pmu(&power7_pmu);
+}
+
+arch_initcall(init_power7_pmu);
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c
index 3ed8833..6637c87 100644
--- a/arch/powerpc/kernel/ppc970-pmu.c
+++ b/arch/powerpc/kernel/ppc970-pmu.c
@@ -10,7 +10,9 @@
*/
#include <linux/string.h>
#include <linux/perf_counter.h>
+#include <linux/string.h>
#include <asm/reg.h>
+#include <asm/cputable.h>
/*
* Bits in event code for PPC970
@@ -470,7 +472,8 @@ static int ppc970_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
},
};
-struct power_pmu ppc970_pmu = {
+static struct power_pmu ppc970_pmu = {
+ .name = "PPC970/FX/MP",
.n_counter = 8,
.max_alternatives = 2,
.add_fields = 0x001100005555ull,
@@ -483,3 +486,14 @@ struct power_pmu ppc970_pmu = {
.generic_events = ppc970_generic_events,
.cache_events = &ppc970_cache_events,
};
+
+static int init_ppc970_pmu(void)
+{
+ if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970")
+ && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970MP"))
+ return -ENODEV;
+
+ return register_power_pmu(&ppc970_pmu);
+}
+
+arch_initcall(init_ppc970_pmu);
--
1.6.0.4
^ permalink raw reply related
* [PATCH 5/6] perf_counter: powerpc: Add processor back-end for MPC7450 family
From: Paul Mackerras @ 2009-06-17 11:53 UTC (permalink / raw)
To: Ingo Molnar, benh; +Cc: linuxppc-dev, Peter Zijlstra, linux-kernel
In-Reply-To: <19000.55404.103840.393470@cargo.ozlabs.ibm.com>
This adds support for the performance monitor hardware on the
MPC7450 family of processors (7450, 7451, 7455, 7447/7457, 7447A,
7448), used in the later Apple G4 powermacs/powerbooks and other
machines. These machines have 6 hardware counters with a unique
set of events which can be counted on each counter, with some
events being available on multiple counters.
Raw event codes for these processors are (PMC << 8) + PMCSEL.
If PMC is non-zero then the event is that selected by the given
PMCSEL value for that PMC (hardware counter). If PMC is zero
then the event selected is one of the low-numbered ones that are
common to several PMCs. In this case PMCSEL must be <= 22 and
the event is what that PMCSEL value would select on PMC1 (but
it may be placed any other PMC that has the same event for that
PMCSEL value).
For events that count cycles or occurrences that exceed a threshold,
the threshold requested can be specified in the 0x3f000 bits of the
raw event codes. If the event uses the threshold multiplier bit
and that bit should be set, that is indicated with the 0x40000 bit
of the raw event code.
This fills in some of the generic cache events. Unfortunately there
are quite a few blank spaces in the table, partly because these
processors tend to count cache hits rather than cache accesses.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
arch/powerpc/kernel/Makefile | 2 +
arch/powerpc/kernel/mpc7450-pmu.c | 417 ++++++++++++++++++++++++++++++++
arch/powerpc/platforms/Kconfig.cputype | 1 +
3 files changed, 420 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/kernel/mpc7450-pmu.c
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index c5f93f0..a9f8829 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -98,6 +98,7 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_PPC_PERF_CTRS) += perf_counter.o
obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \
power5+-pmu.o power6-pmu.o power7-pmu.o
+obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o
obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
@@ -106,6 +107,7 @@ obj-y += iomap.o
endif
obj-$(CONFIG_PPC64) += $(obj64-y)
+obj-$(CONFIG_PPC32) += $(obj32-y)
ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
obj-y += ppc_save_regs.o
diff --git a/arch/powerpc/kernel/mpc7450-pmu.c b/arch/powerpc/kernel/mpc7450-pmu.c
new file mode 100644
index 0000000..75ff47f
--- /dev/null
+++ b/arch/powerpc/kernel/mpc7450-pmu.c
@@ -0,0 +1,417 @@
+/*
+ * Performance counter support for MPC7450-family processors.
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ *
+ * 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/string.h>
+#include <linux/perf_counter.h>
+#include <linux/string.h>
+#include <asm/reg.h>
+#include <asm/cputable.h>
+
+#define N_COUNTER 6 /* Number of hardware counters */
+#define MAX_ALT 3 /* Maximum number of event alternative codes */
+
+/*
+ * Bits in event code for MPC7450 family
+ */
+#define PM_THRMULT_MSKS 0x40000
+#define PM_THRESH_SH 12
+#define PM_THRESH_MSK 0x3f
+#define PM_PMC_SH 8
+#define PM_PMC_MSK 7
+#define PM_PMCSEL_MSK 0x7f
+
+/*
+ * Classify events according to how specific their PMC requirements are.
+ * Result is:
+ * 0: can go on any PMC
+ * 1: can go on PMCs 1-4
+ * 2: can go on PMCs 1,2,4
+ * 3: can go on PMCs 1 or 2
+ * 4: can only go on one PMC
+ * -1: event code is invalid
+ */
+#define N_CLASSES 5
+
+static int mpc7450_classify_event(u32 event)
+{
+ int pmc;
+
+ pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+ if (pmc) {
+ if (pmc > N_COUNTER)
+ return -1;
+ return 4;
+ }
+ event &= PM_PMCSEL_MSK;
+ if (event <= 1)
+ return 0;
+ if (event <= 7)
+ return 1;
+ if (event <= 13)
+ return 2;
+ if (event <= 22)
+ return 3;
+ return -1;
+}
+
+/*
+ * Events using threshold and possible threshold scale:
+ * code scale? name
+ * 11e N PM_INSTQ_EXCEED_CYC
+ * 11f N PM_ALTV_IQ_EXCEED_CYC
+ * 128 Y PM_DTLB_SEARCH_EXCEED_CYC
+ * 12b Y PM_LD_MISS_EXCEED_L1_CYC
+ * 220 N PM_CQ_EXCEED_CYC
+ * 30c N PM_GPR_RB_EXCEED_CYC
+ * 30d ? PM_FPR_IQ_EXCEED_CYC ?
+ * 311 Y PM_ITLB_SEARCH_EXCEED
+ * 410 N PM_GPR_IQ_EXCEED_CYC
+ */
+
+/*
+ * Return use of threshold and threshold scale bits:
+ * 0 = uses neither, 1 = uses threshold, 2 = uses both
+ */
+static int mpc7450_threshold_use(u32 event)
+{
+ int pmc, sel;
+
+ pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+ sel = event & PM_PMCSEL_MSK;
+ switch (pmc) {
+ case 1:
+ if (sel == 0x1e || sel == 0x1f)
+ return 1;
+ if (sel == 0x28 || sel == 0x2b)
+ return 2;
+ break;
+ case 2:
+ if (sel == 0x20)
+ return 1;
+ break;
+ case 3:
+ if (sel == 0xc || sel == 0xd)
+ return 1;
+ if (sel == 0x11)
+ return 2;
+ break;
+ case 4:
+ if (sel == 0x10)
+ return 1;
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Layout of constraint bits:
+ * 33222222222211111111110000000000
+ * 10987654321098765432109876543210
+ * |< >< > < > < ><><><><><><>
+ * TS TV G4 G3 G2P6P5P4P3P2P1
+ *
+ * P1 - P6
+ * 0 - 11: Count of events needing PMC1 .. PMC6
+ *
+ * G2
+ * 12 - 14: Count of events needing PMC1 or PMC2
+ *
+ * G3
+ * 16 - 18: Count of events needing PMC1, PMC2 or PMC4
+ *
+ * G4
+ * 20 - 23: Count of events needing PMC1, PMC2, PMC3 or PMC4
+ *
+ * TV
+ * 24 - 29: Threshold value requested
+ *
+ * TS
+ * 30: Threshold scale value requested
+ */
+
+static u32 pmcbits[N_COUNTER][2] = {
+ { 0x00844002, 0x00111001 }, /* PMC1 mask, value: P1,G2,G3,G4 */
+ { 0x00844008, 0x00111004 }, /* PMC2: P2,G2,G3,G4 */
+ { 0x00800020, 0x00100010 }, /* PMC3: P3,G4 */
+ { 0x00840080, 0x00110040 }, /* PMC4: P4,G3,G4 */
+ { 0x00000200, 0x00000100 }, /* PMC5: P5 */
+ { 0x00000800, 0x00000400 } /* PMC6: P6 */
+};
+
+static u32 classbits[N_CLASSES - 1][2] = {
+ { 0x00000000, 0x00000000 }, /* class 0: no constraint */
+ { 0x00800000, 0x00100000 }, /* class 1: G4 */
+ { 0x00040000, 0x00010000 }, /* class 2: G3 */
+ { 0x00004000, 0x00001000 }, /* class 3: G2 */
+};
+
+static int mpc7450_get_constraint(u64 event, unsigned long *maskp,
+ unsigned long *valp)
+{
+ int pmc, class;
+ u32 mask, value;
+ int thresh, tuse;
+
+ class = mpc7450_classify_event(event);
+ if (class < 0)
+ return -1;
+ if (class == 4) {
+ pmc = ((unsigned int)event >> PM_PMC_SH) & PM_PMC_MSK;
+ mask = pmcbits[pmc - 1][0];
+ value = pmcbits[pmc - 1][1];
+ } else {
+ mask = classbits[class][0];
+ value = classbits[class][1];
+ }
+
+ tuse = mpc7450_threshold_use(event);
+ if (tuse) {
+ thresh = ((unsigned int)event >> PM_THRESH_SH) & PM_THRESH_MSK;
+ mask |= 0x3f << 24;
+ value |= thresh << 24;
+ if (tuse == 2) {
+ mask |= 0x40000000;
+ if ((unsigned int)event & PM_THRMULT_MSKS)
+ value |= 0x40000000;
+ }
+ }
+
+ *maskp = mask;
+ *valp = value;
+ return 0;
+}
+
+static const unsigned int event_alternatives[][MAX_ALT] = {
+ { 0x217, 0x317 }, /* PM_L1_DCACHE_MISS */
+ { 0x418, 0x50f, 0x60f }, /* PM_SNOOP_RETRY */
+ { 0x502, 0x602 }, /* PM_L2_HIT */
+ { 0x503, 0x603 }, /* PM_L3_HIT */
+ { 0x504, 0x604 }, /* PM_L2_ICACHE_MISS */
+ { 0x505, 0x605 }, /* PM_L3_ICACHE_MISS */
+ { 0x506, 0x606 }, /* PM_L2_DCACHE_MISS */
+ { 0x507, 0x607 }, /* PM_L3_DCACHE_MISS */
+ { 0x50a, 0x623 }, /* PM_LD_HIT_L3 */
+ { 0x50b, 0x624 }, /* PM_ST_HIT_L3 */
+ { 0x50d, 0x60d }, /* PM_L2_TOUCH_HIT */
+ { 0x50e, 0x60e }, /* PM_L3_TOUCH_HIT */
+ { 0x512, 0x612 }, /* PM_INT_LOCAL */
+ { 0x513, 0x61d }, /* PM_L2_MISS */
+ { 0x514, 0x61e }, /* PM_L3_MISS */
+};
+
+/*
+ * Scan the alternatives table for a match and return the
+ * index into the alternatives table if found, else -1.
+ */
+static int find_alternative(u32 event)
+{
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
+ if (event < event_alternatives[i][0])
+ break;
+ for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j)
+ if (event == event_alternatives[i][j])
+ return i;
+ }
+ return -1;
+}
+
+static int mpc7450_get_alternatives(u64 event, unsigned int flags, u64 alt[])
+{
+ int i, j, nalt = 1;
+ u32 ae;
+
+ alt[0] = event;
+ nalt = 1;
+ i = find_alternative((u32)event);
+ if (i >= 0) {
+ for (j = 0; j < MAX_ALT; ++j) {
+ ae = event_alternatives[i][j];
+ if (ae && ae != (u32)event)
+ alt[nalt++] = ae;
+ }
+ }
+ return nalt;
+}
+
+/*
+ * Bitmaps of which PMCs each class can use for classes 0 - 3.
+ * Bit i is set if PMC i+1 is usable.
+ */
+static const u8 classmap[N_CLASSES] = {
+ 0x3f, 0x0f, 0x0b, 0x03, 0
+};
+
+/* Bit position and width of each PMCSEL field */
+static const int pmcsel_shift[N_COUNTER] = {
+ 6, 0, 27, 22, 17, 11
+};
+static const u32 pmcsel_mask[N_COUNTER] = {
+ 0x7f, 0x3f, 0x1f, 0x1f, 0x1f, 0x3f
+};
+
+/*
+ * Compute MMCR0/1/2 values for a set of events.
+ */
+static int mpc7450_compute_mmcr(u64 event[], int n_ev,
+ unsigned int hwc[], unsigned long mmcr[])
+{
+ u8 event_index[N_CLASSES][N_COUNTER];
+ int n_classevent[N_CLASSES];
+ int i, j, class, tuse;
+ u32 pmc_inuse = 0, pmc_avail;
+ u32 mmcr0 = 0, mmcr1 = 0, mmcr2 = 0;
+ u32 ev, pmc, thresh;
+
+ if (n_ev > N_COUNTER)
+ return -1;
+
+ /* First pass: count usage in each class */
+ for (i = 0; i < N_CLASSES; ++i)
+ n_classevent[i] = 0;
+ for (i = 0; i < n_ev; ++i) {
+ class = mpc7450_classify_event(event[i]);
+ if (class < 0)
+ return -1;
+ j = n_classevent[class]++;
+ event_index[class][j] = i;
+ }
+
+ /* Second pass: allocate PMCs from most specific event to least */
+ for (class = N_CLASSES - 1; class >= 0; --class) {
+ for (i = 0; i < n_classevent[class]; ++i) {
+ ev = event[event_index[class][i]];
+ if (class == 4) {
+ pmc = (ev >> PM_PMC_SH) & PM_PMC_MSK;
+ if (pmc_inuse & (1 << (pmc - 1)))
+ return -1;
+ } else {
+ /* Find a suitable PMC */
+ pmc_avail = classmap[class] & ~pmc_inuse;
+ if (!pmc_avail)
+ return -1;
+ pmc = ffs(pmc_avail);
+ }
+ pmc_inuse |= 1 << (pmc - 1);
+
+ tuse = mpc7450_threshold_use(ev);
+ if (tuse) {
+ thresh = (ev >> PM_THRESH_SH) & PM_THRESH_MSK;
+ mmcr0 |= thresh << 16;
+ if (tuse == 2 && (ev & PM_THRMULT_MSKS))
+ mmcr2 = 0x80000000;
+ }
+ ev &= pmcsel_mask[pmc - 1];
+ ev <<= pmcsel_shift[pmc - 1];
+ if (pmc <= 2)
+ mmcr0 |= ev;
+ else
+ mmcr1 |= ev;
+ hwc[event_index[class][i]] = pmc - 1;
+ }
+ }
+
+ if (pmc_inuse & 1)
+ mmcr0 |= MMCR0_PMC1CE;
+ if (pmc_inuse & 0x3e)
+ mmcr0 |= MMCR0_PMCnCE;
+
+ /* Return MMCRx values */
+ mmcr[0] = mmcr0;
+ mmcr[1] = mmcr1;
+ mmcr[2] = mmcr2;
+ return 0;
+}
+
+/*
+ * Disable counting by a PMC.
+ * Note that the pmc argument is 0-based here, not 1-based.
+ */
+static void mpc7450_disable_pmc(unsigned int pmc, unsigned long mmcr[])
+{
+ if (pmc <= 1)
+ mmcr[0] &= ~(pmcsel_mask[pmc] << pmcsel_shift[pmc]);
+ else
+ mmcr[1] &= ~(pmcsel_mask[pmc] << pmcsel_shift[pmc]);
+}
+
+static int mpc7450_generic_events[] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = 1,
+ [PERF_COUNT_HW_INSTRUCTIONS] = 2,
+ [PERF_COUNT_HW_CACHE_MISSES] = 0x217, /* PM_L1_DCACHE_MISS */
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x122, /* PM_BR_CMPL */
+ [PERF_COUNT_HW_BRANCH_MISSES] = 0x41c, /* PM_BR_MPRED */
+};
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ */
+static int mpc7450_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+ [C(L1D)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 0, 0x225 },
+ [C(OP_WRITE)] = { 0, 0x227 },
+ [C(OP_PREFETCH)] = { 0, 0 },
+ },
+ [C(L1I)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 0x129, 0x115 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { 0x634, 0 },
+ },
+ [C(LL)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 0, 0 },
+ [C(OP_WRITE)] = { 0, 0 },
+ [C(OP_PREFETCH)] = { 0, 0 },
+ },
+ [C(DTLB)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 0, 0x312 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
+ [C(ITLB)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 0, 0x223 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
+ [C(BPU)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 0x122, 0x41c },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
+};
+
+struct power_pmu mpc7450_pmu = {
+ .name = "MPC7450 family",
+ .n_counter = N_COUNTER,
+ .max_alternatives = MAX_ALT,
+ .add_fields = 0x00111555ul,
+ .test_adder = 0x00301000ul,
+ .compute_mmcr = mpc7450_compute_mmcr,
+ .get_constraint = mpc7450_get_constraint,
+ .get_alternatives = mpc7450_get_alternatives,
+ .disable_pmc = mpc7450_disable_pmc,
+ .n_generic = ARRAY_SIZE(mpc7450_generic_events),
+ .generic_events = mpc7450_generic_events,
+ .cache_events = &mpc7450_cache_events,
+};
+
+static int init_mpc7450_pmu(void)
+{
+ if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/7450"))
+ return -ENODEV;
+
+ return register_power_pmu(&mpc7450_pmu);
+}
+
+arch_initcall(init_mpc7450_pmu);
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index dd9f3ec..8485c8c 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -75,6 +75,7 @@ config POWER4_ONLY
config 6xx
def_bool y
depends on PPC32 && PPC_BOOK3S
+ select PPC_HAVE_PMU_SUPPORT
config POWER3
bool
--
1.6.0.4
^ permalink raw reply related
* [PATCH 6/6] perf_counter: tools: Makefile tweaks for 64-bit powerpc
From: Paul Mackerras @ 2009-06-17 11:54 UTC (permalink / raw)
To: Ingo Molnar, benh; +Cc: linuxppc-dev, Peter Zijlstra, linux-kernel
In-Reply-To: <19000.55404.103840.393470@cargo.ozlabs.ibm.com>
On 64-bit powerpc, perf needs to be built as a 64-bit executable.
This arranges to add the -m64 flag to CFLAGS if we are running on
a 64-bit machine, indicated by the result of uname -m ending in "64".
This means that we'll use -m64 on x86_64 machines as well.
This also removes the -Werror flag when building on a 64-bit powerpc
machine. The userspace definition of u64 is unsigned long rather
than unsigned long long, meaning that gcc warns every time a u64
is printed with %Lx or %llx (though that does work properly).
In future we may use PRI64 etc. for printing 64-bit quantities,
which would eliminate these warnings.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
tools/perf/Makefile | 14 +++++++++++++-
1 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index e8346f9..eddd61a 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -157,9 +157,21 @@ uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
+# If we're on a 64-bit kernel, use -m64
+ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
+ M64 := -m64
+endif
+
+# Don't use -Werror on ppc64; we get warnings due to using
+# %Lx formats on __u64, which is unsigned long.
+Werror := -Werror
+ifeq ($(uname_M),ppc64)
+ Werror :=
+endif
+
# CFLAGS and LDFLAGS are for the users to override from the command line.
-CFLAGS = -ggdb3 -Wall -Werror -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -O6
+CFLAGS = $(M64) -ggdb3 -Wall $(Werror) -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -O6
LDFLAGS = -lpthread -lrt -lelf -lm
ALL_CFLAGS = $(CFLAGS)
ALL_LDFLAGS = $(LDFLAGS)
--
1.6.0.4
^ permalink raw reply related
* [PATCH 4/6] perf_counter: powerpc: Make powerpc perf_counter code safe for 32-bit kernels
From: Paul Mackerras @ 2009-06-17 11:53 UTC (permalink / raw)
To: Ingo Molnar, benh; +Cc: linuxppc-dev, Peter Zijlstra, linux-kernel
In-Reply-To: <19000.55404.103840.393470@cargo.ozlabs.ibm.com>
This abstracts a few things in arch/powerpc/kernel/perf_counter.c
that are specific to 64-bit kernels, and provides definitions for
32-bit kernels. In particular,
* Only 64-bit has MMCRA and the bits in it that give information
about a PMU interrupt (sampled PR, HV, slot number etc.)
* Only 64-bit has the lppaca and the lppaca->pmcregs_in_use field
* Use of SDAR is confined to 64-bit for now
* Only 64-bit has soft/lazy interrupt disable and therefore
pseudo-NMIs (interrupts that occur while interrupts are soft-disabled)
* Only 64-bit has PMC7 and PMC8
* Only 64-bit has the MSR_HV bit.
This also fixes the types used in a couple of places, where we were
using long types for things that need to be 64-bit.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
arch/powerpc/kernel/perf_counter.c | 193 +++++++++++++++++++++++++-----------
1 files changed, 133 insertions(+), 60 deletions(-)
diff --git a/arch/powerpc/kernel/perf_counter.c b/arch/powerpc/kernel/perf_counter.c
index 54e0489..809fdf9 100644
--- a/arch/powerpc/kernel/perf_counter.c
+++ b/arch/powerpc/kernel/perf_counter.c
@@ -46,6 +46,115 @@ struct power_pmu *ppmu;
*/
static unsigned int freeze_counters_kernel = MMCR0_FCS;
+/*
+ * 32-bit doesn't have MMCRA but does have an MMCR2,
+ * and a few other names are different.
+ */
+#ifdef CONFIG_PPC32
+
+#define MMCR0_FCHV 0
+#define MMCR0_PMCjCE MMCR0_PMCnCE
+
+#define SPRN_MMCRA SPRN_MMCR2
+#define MMCRA_SAMPLE_ENABLE 0
+
+static inline unsigned long perf_ip_adjust(struct pt_regs *regs)
+{
+ return 0;
+}
+static inline void perf_set_pmu_inuse(int inuse) { }
+static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp) { }
+static inline u32 perf_get_misc_flags(struct pt_regs *regs)
+{
+ return 0;
+}
+static inline void perf_read_regs(struct pt_regs *regs) { }
+static inline int perf_intr_is_nmi(struct pt_regs *regs)
+{
+ return 0;
+}
+
+#endif /* CONFIG_PPC32 */
+
+/*
+ * Things that are specific to 64-bit implementations.
+ */
+#ifdef CONFIG_PPC64
+
+static inline unsigned long perf_ip_adjust(struct pt_regs *regs)
+{
+ unsigned long mmcra = regs->dsisr;
+
+ if ((mmcra & MMCRA_SAMPLE_ENABLE) && !(ppmu->flags & PPMU_ALT_SIPR)) {
+ unsigned long slot = (mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT;
+ if (slot > 1)
+ return 4 * (slot - 1);
+ }
+ return 0;
+}
+
+static inline void perf_set_pmu_inuse(int inuse)
+{
+ get_lppaca()->pmcregs_in_use = inuse;
+}
+
+/*
+ * The user wants a data address recorded.
+ * If we're not doing instruction sampling, give them the SDAR
+ * (sampled data address). If we are doing instruction sampling, then
+ * only give them the SDAR if it corresponds to the instruction
+ * pointed to by SIAR; this is indicated by the [POWER6_]MMCRA_SDSYNC
+ * bit in MMCRA.
+ */
+static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
+{
+ unsigned long mmcra = regs->dsisr;
+ unsigned long sdsync = (ppmu->flags & PPMU_ALT_SIPR) ?
+ POWER6_MMCRA_SDSYNC : MMCRA_SDSYNC;
+
+ if (!(mmcra & MMCRA_SAMPLE_ENABLE) || (mmcra & sdsync))
+ *addrp = mfspr(SPRN_SDAR);
+}
+
+static inline u32 perf_get_misc_flags(struct pt_regs *regs)
+{
+ unsigned long mmcra = regs->dsisr;
+
+ if (TRAP(regs) != 0xf00)
+ return 0; /* not a PMU interrupt */
+
+ if (ppmu->flags & PPMU_ALT_SIPR) {
+ if (mmcra & POWER6_MMCRA_SIHV)
+ return PERF_EVENT_MISC_HYPERVISOR;
+ return (mmcra & POWER6_MMCRA_SIPR) ?
+ PERF_EVENT_MISC_USER : PERF_EVENT_MISC_KERNEL;
+ }
+ if (mmcra & MMCRA_SIHV)
+ return PERF_EVENT_MISC_HYPERVISOR;
+ return (mmcra & MMCRA_SIPR) ? PERF_EVENT_MISC_USER :
+ PERF_EVENT_MISC_KERNEL;
+}
+
+/*
+ * Overload regs->dsisr to store MMCRA so we only need to read it once
+ * on each interrupt.
+ */
+static inline void perf_read_regs(struct pt_regs *regs)
+{
+ regs->dsisr = mfspr(SPRN_MMCRA);
+}
+
+/*
+ * If interrupts were soft-disabled when a PMU interrupt occurs, treat
+ * it as an NMI.
+ */
+static inline int perf_intr_is_nmi(struct pt_regs *regs)
+{
+ return !regs->softe;
+}
+
+#endif /* CONFIG_PPC64 */
+
static void perf_counter_interrupt(struct pt_regs *regs);
void perf_counter_print_debug(void)
@@ -78,12 +187,14 @@ static unsigned long read_pmc(int idx)
case 6:
val = mfspr(SPRN_PMC6);
break;
+#ifdef CONFIG_PPC64
case 7:
val = mfspr(SPRN_PMC7);
break;
case 8:
val = mfspr(SPRN_PMC8);
break;
+#endif /* CONFIG_PPC64 */
default:
printk(KERN_ERR "oops trying to read PMC%d\n", idx);
val = 0;
@@ -115,12 +226,14 @@ static void write_pmc(int idx, unsigned long val)
case 6:
mtspr(SPRN_PMC6, val);
break;
+#ifdef CONFIG_PPC64
case 7:
mtspr(SPRN_PMC7, val);
break;
case 8:
mtspr(SPRN_PMC8, val);
break;
+#endif /* CONFIG_PPC64 */
default:
printk(KERN_ERR "oops trying to write PMC%d\n", idx);
}
@@ -283,7 +396,7 @@ static int check_excludes(struct perf_counter **ctrs, unsigned int cflags[],
static void power_pmu_read(struct perf_counter *counter)
{
- long val, delta, prev;
+ s64 val, delta, prev;
if (!counter->hw.idx)
return;
@@ -477,7 +590,7 @@ void hw_perf_enable(void)
mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
mtspr(SPRN_MMCR1, cpuhw->mmcr[1]);
if (cpuhw->n_counters == 0)
- get_lppaca()->pmcregs_in_use = 0;
+ perf_set_pmu_inuse(0);
goto out_enable;
}
@@ -510,7 +623,7 @@ void hw_perf_enable(void)
* bit set and set the hardware counters to their initial values.
* Then unfreeze the counters.
*/
- get_lppaca()->pmcregs_in_use = 1;
+ perf_set_pmu_inuse(1);
mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
mtspr(SPRN_MMCR1, cpuhw->mmcr[1]);
mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE))
@@ -1007,13 +1120,12 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter)
* things if requested. Note that interrupts are hard-disabled
* here so there is no possibility of being interrupted.
*/
-static void record_and_restart(struct perf_counter *counter, long val,
+static void record_and_restart(struct perf_counter *counter, unsigned long val,
struct pt_regs *regs, int nmi)
{
u64 period = counter->hw.sample_period;
s64 prev, delta, left;
int record = 0;
- unsigned long mmcra, sdsync;
/* we don't have to worry about interrupts here */
prev = atomic64_read(&counter->hw.prev_count);
@@ -1033,8 +1145,8 @@ static void record_and_restart(struct perf_counter *counter, long val,
left = period;
record = 1;
}
- if (left < 0x80000000L)
- val = 0x80000000L - left;
+ if (left < 0x80000000LL)
+ val = 0x80000000LL - left;
}
/*
@@ -1047,22 +1159,9 @@ static void record_and_restart(struct perf_counter *counter, long val,
.period = counter->hw.last_period,
};
- if (counter->attr.sample_type & PERF_SAMPLE_ADDR) {
- /*
- * The user wants a data address recorded.
- * If we're not doing instruction sampling,
- * give them the SDAR (sampled data address).
- * If we are doing instruction sampling, then only
- * give them the SDAR if it corresponds to the
- * instruction pointed to by SIAR; this is indicated
- * by the [POWER6_]MMCRA_SDSYNC bit in MMCRA.
- */
- mmcra = regs->dsisr;
- sdsync = (ppmu->flags & PPMU_ALT_SIPR) ?
- POWER6_MMCRA_SDSYNC : MMCRA_SDSYNC;
- if (!(mmcra & MMCRA_SAMPLE_ENABLE) || (mmcra & sdsync))
- data.addr = mfspr(SPRN_SDAR);
- }
+ if (counter->attr.sample_type & PERF_SAMPLE_ADDR)
+ perf_get_data_addr(regs, &data.addr);
+
if (perf_counter_overflow(counter, nmi, &data)) {
/*
* Interrupts are coming too fast - throttle them
@@ -1088,25 +1187,12 @@ static void record_and_restart(struct perf_counter *counter, long val,
*/
unsigned long perf_misc_flags(struct pt_regs *regs)
{
- unsigned long mmcra;
+ u32 flags = perf_get_misc_flags(regs);
- if (TRAP(regs) != 0xf00) {
- /* not a PMU interrupt */
- return user_mode(regs) ? PERF_EVENT_MISC_USER :
- PERF_EVENT_MISC_KERNEL;
- }
-
- mmcra = regs->dsisr;
- if (ppmu->flags & PPMU_ALT_SIPR) {
- if (mmcra & POWER6_MMCRA_SIHV)
- return PERF_EVENT_MISC_HYPERVISOR;
- return (mmcra & POWER6_MMCRA_SIPR) ? PERF_EVENT_MISC_USER :
- PERF_EVENT_MISC_KERNEL;
- }
- if (mmcra & MMCRA_SIHV)
- return PERF_EVENT_MISC_HYPERVISOR;
- return (mmcra & MMCRA_SIPR) ? PERF_EVENT_MISC_USER :
- PERF_EVENT_MISC_KERNEL;
+ if (flags)
+ return flags;
+ return user_mode(regs) ? PERF_EVENT_MISC_USER :
+ PERF_EVENT_MISC_KERNEL;
}
/*
@@ -1115,20 +1201,12 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
*/
unsigned long perf_instruction_pointer(struct pt_regs *regs)
{
- unsigned long mmcra;
unsigned long ip;
- unsigned long slot;
if (TRAP(regs) != 0xf00)
return regs->nip; /* not a PMU interrupt */
- ip = mfspr(SPRN_SIAR);
- mmcra = regs->dsisr;
- if ((mmcra & MMCRA_SAMPLE_ENABLE) && !(ppmu->flags & PPMU_ALT_SIPR)) {
- slot = (mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT;
- if (slot > 1)
- ip += 4 * (slot - 1);
- }
+ ip = mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
return ip;
}
@@ -1140,7 +1218,7 @@ static void perf_counter_interrupt(struct pt_regs *regs)
int i;
struct cpu_hw_counters *cpuhw = &__get_cpu_var(cpu_hw_counters);
struct perf_counter *counter;
- long val;
+ unsigned long val;
int found = 0;
int nmi;
@@ -1148,16 +1226,9 @@ static void perf_counter_interrupt(struct pt_regs *regs)
freeze_limited_counters(cpuhw, mfspr(SPRN_PMC5),
mfspr(SPRN_PMC6));
- /*
- * Overload regs->dsisr to store MMCRA so we only need to read it once.
- */
- regs->dsisr = mfspr(SPRN_MMCRA);
+ perf_read_regs(regs);
- /*
- * If interrupts were soft-disabled when this PMU interrupt
- * occurred, treat it as an NMI.
- */
- nmi = !regs->softe;
+ nmi = perf_intr_is_nmi(regs);
if (nmi)
nmi_enter();
else
@@ -1223,11 +1294,13 @@ int register_power_pmu(struct power_pmu *pmu)
pr_info("%s performance monitor hardware support registered\n",
pmu->name);
+#ifdef MSR_HV
/*
* Use FCHV to ignore kernel events if MSR.HV is set.
*/
if (mfmsr() & MSR_HV)
freeze_counters_kernel = MMCR0_FCHV;
+#endif /* CONFIG_PPC64 */
return 0;
}
--
1.6.0.4
^ permalink raw reply related
* [PATCH 1/6] perf_counter: powerpc: Enable use of software counters on 32-bit powerpc
From: Paul Mackerras @ 2009-06-17 11:50 UTC (permalink / raw)
To: Ingo Molnar, benh; +Cc: linuxppc-dev, Peter Zijlstra, linux-kernel
This enables the perf_counter subsystem on 32-bit powerpc. Since we
don't have any support for hardware counters on 32-bit powerpc yet,
only software counters can be used.
Besides selecting HAVE_PERF_COUNTERS for 32-bit powerpc as well as
64-bit, the main thing this does is add an implementation of
set_perf_counter_pending(). This needs to arrange for
perf_counter_do_pending() to be called when interrupts are enabled.
Rather than add code to local_irq_restore as 64-bit does, the 32-bit
set_perf_counter_pending() generates an interrupt by setting the
decrementer to 1 so that a decrementer interrupt will become pending
in 1 or 2 timebase ticks (if a decrementer interrupt isn't already
pending). When interrupts are enabled, timer_interrupt() will be
called, and some new code in there calls perf_counter_do_pending().
We use a per-cpu array of flags to indicate whether we need to call
perf_counter_do_pending() or not.
This introduces a couple of new Kconfig symbols: PPC_HAVE_PMU_SUPPORT,
which is selected by processor families for which we have hardware PMU
support (currently only PPC64), and PPC_PERF_CTRS, which enables the
powerpc-specific perf_counter back-end.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
This depends on the generic atomic64_t patches, which are now in
Linus' tree. Ingo, if you're putting these in, please pull Linus'
tree in first.
arch/powerpc/Kconfig | 1 +
arch/powerpc/include/asm/hw_irq.h | 5 ++++-
arch/powerpc/include/asm/perf_counter.h | 10 ++++++++--
arch/powerpc/kernel/Makefile | 6 +++---
arch/powerpc/kernel/time.c | 25 +++++++++++++++++++++++++
arch/powerpc/platforms/Kconfig.cputype | 11 ++++++++++-
6 files changed, 51 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 9fb344d..bf6cedf 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -126,6 +126,7 @@ config PPC
select HAVE_OPROFILE
select HAVE_SYSCALL_WRAPPERS if PPC64
select GENERIC_ATOMIC64 if PPC32
+ select HAVE_PERF_COUNTERS
config EARLY_PRINTK
bool
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index 10a642d..867ab8e 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -131,6 +131,8 @@ static inline int irqs_disabled_flags(unsigned long flags)
struct irq_chip;
#ifdef CONFIG_PERF_COUNTERS
+
+#ifdef CONFIG_PPC64
static inline unsigned long test_perf_counter_pending(void)
{
unsigned long x;
@@ -154,8 +156,9 @@ static inline void clear_perf_counter_pending(void)
"r" (0),
"i" (offsetof(struct paca_struct, perf_counter_pending)));
}
+#endif /* CONFIG_PPC64 */
-#else
+#else /* CONFIG_PERF_COUNTERS */
static inline unsigned long test_perf_counter_pending(void)
{
diff --git a/arch/powerpc/include/asm/perf_counter.h b/arch/powerpc/include/asm/perf_counter.h
index b398a84..2c2d9f6 100644
--- a/arch/powerpc/include/asm/perf_counter.h
+++ b/arch/powerpc/include/asm/perf_counter.h
@@ -57,11 +57,17 @@ extern struct power_pmu *ppmu;
struct pt_regs;
extern unsigned long perf_misc_flags(struct pt_regs *regs);
-#define perf_misc_flags(regs) perf_misc_flags(regs)
-
extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
/*
+ * Only override the default definitions in include/linux/perf_counter.h
+ * if we have hardware PMU support.
+ */
+#ifdef CONFIG_PPC_PERF_CTRS
+#define perf_misc_flags(regs) perf_misc_flags(regs)
+#endif
+
+/*
* The power_pmu.get_constraint function returns a 64-bit value and
* a 64-bit mask that express the constraints between this event and
* other events.
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 612b0c4..c5f93f0 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -95,9 +95,9 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
-obj-$(CONFIG_PERF_COUNTERS) += perf_counter.o power4-pmu.o ppc970-pmu.o \
- power5-pmu.o power5+-pmu.o power6-pmu.o \
- power7-pmu.o
+obj-$(CONFIG_PPC_PERF_CTRS) += perf_counter.o
+obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \
+ power5+-pmu.o power6-pmu.o power7-pmu.o
obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 15391c2..eae4511 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -53,6 +53,7 @@
#include <linux/posix-timers.h>
#include <linux/irq.h>
#include <linux/delay.h>
+#include <linux/perf_counter.h>
#include <asm/io.h>
#include <asm/processor.h>
@@ -525,6 +526,26 @@ void __init iSeries_time_init_early(void)
}
#endif /* CONFIG_PPC_ISERIES */
+#if defined(CONFIG_PERF_COUNTERS) && defined(CONFIG_PPC32)
+DEFINE_PER_CPU(u8, perf_counter_pending);
+
+void set_perf_counter_pending(void)
+{
+ get_cpu_var(perf_counter_pending) = 1;
+ set_dec(1);
+ put_cpu_var(perf_counter_pending);
+}
+
+#define test_perf_counter_pending() __get_cpu_var(perf_counter_pending)
+#define clear_perf_counter_pending() __get_cpu_var(perf_counter_pending) = 0
+
+#else /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */
+
+#define test_perf_counter_pending() 0
+#define clear_perf_counter_pending()
+
+#endif /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */
+
/*
* For iSeries shared processors, we have to let the hypervisor
* set the hardware decrementer. We set a virtual decrementer
@@ -551,6 +572,10 @@ void timer_interrupt(struct pt_regs * regs)
set_dec(DECREMENTER_MAX);
#ifdef CONFIG_PPC32
+ if (test_perf_counter_pending()) {
+ clear_perf_counter_pending();
+ perf_counter_do_pending();
+ }
if (atomic_read(&ppc_n_lost_interrupts) != 0)
do_IRQ(regs);
#endif
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index cca6b4f..dd9f3ec 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -1,7 +1,7 @@
config PPC64
bool "64-bit kernel"
default n
- select HAVE_PERF_COUNTERS
+ select PPC_HAVE_PMU_SUPPORT
help
This option selects whether a 32-bit or a 64-bit kernel
will be built.
@@ -243,6 +243,15 @@ config VIRT_CPU_ACCOUNTING
If in doubt, say Y here.
+config PPC_HAVE_PMU_SUPPORT
+ bool
+
+config PPC_PERF_CTRS
+ def_bool y
+ depends on PERF_COUNTERS && PPC_HAVE_PMU_SUPPORT
+ help
+ This enables the powerpc-specific perf_counter back-end.
+
config SMP
depends on PPC_STD_MMU || FSL_BOOKE
bool "Symmetric multi-processing support"
--
1.6.0.4
^ permalink raw reply related
* [PATCH] Do not inline putprops function
From: M. Mohan Kumar @ 2009-06-17 11:34 UTC (permalink / raw)
To: kexec, linuxppc-dev; +Cc: horms, miltonm
Do not inline putprops function
With the recent kexec-tools git tree, both kexec and kdump kernels hang (i.e
kexec -l and kexec -p respectively). This happened after the patch "ppc64:
cleanups" commit b43a84a31a4be6ed025c1bdef3bb1c3c12e01b16. I tried
reverting each hunk and then found out that retaining following lines in
fs2dt.c makes kexec/kdump work.
-static unsigned *dt_len; /* changed len of modified cmdline
- in flat device-tree */
[....]
- dt_len = dt;
I don't have any clue why removing a unused variable would cause the kexec
kernel to hang. After further investigation, I observed that if the putprops
function is not inlined, kexec/kdump kernel would work even after removing
the above lines.
This patch directs gcc to not inline the putprops function. Now we could
invoke kexec and kdump kernels.
---
kexec/arch/ppc64/fs2dt.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c
index 1f551fd..1e01f74 100644
--- a/kexec/arch/ppc64/fs2dt.c
+++ b/kexec/arch/ppc64/fs2dt.c
@@ -259,7 +259,7 @@ static void add_usable_mem_property(int fd, int len)
}
/* put all properties (files) in the property structure */
-static void putprops(char *fn, struct dirent **nlist, int numlist)
+__attribute__ ((noinline)) static void putprops(char *fn, struct dirent **nlist, int numlist)
{
struct dirent *dp;
int i = 0, fd, len;
--
1.6.0.6
^ permalink raw reply related
* Re: [BUG] lib/kernel_lock.c:126 with cgroups regression ltp tests
From: Michael Ellerman @ 2009-06-17 11:20 UTC (permalink / raw)
To: Sachin Sant
Cc: linux-kernel, linuxppc-dev, Al Viro, menage, abogani,
Balbir Singh
In-Reply-To: <4A38CAAC.4090606@in.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 4657 bytes --]
On Wed, 2009-06-17 at 16:21 +0530, Sachin Sant wrote:
> While executing cgroups regression tests from LTP May 2009
> release on a Power6 box came across the following bug.
> This is with 2.6.30-git10 (300df7dc89cc276377fc020704e34875d5c473b6)
Looks like 337eb00a2 missed some return paths in do_remount_sb()?
$ git log -p -U13 337eb00a2c3a421999c39c94ce7e33545ee8baa7 fs/super.c
commit 337eb00a2c3a421999c39c94ce7e33545ee8baa7
Author: Alessio Igor Bogani <abogani@texware.it>
Date: Tue May 12 15:10:54 2009 +0200
Push BKL down into ->remount_fs()
[xfs, btrfs, capifs, shmem don't need BKL, exempt]
Signed-off-by: Alessio Igor Bogani <abogani@texware.it>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
diff --git a/fs/super.c b/fs/super.c
index 1905f4a..83b4741 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -530,53 +530,51 @@ int do_remount_sb(struct super_block *sb, int flags, void
{
int retval;
int remount_rw;
#ifdef CONFIG_BLOCK
if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev))
return -EACCES;
#endif
if (flags & MS_RDONLY)
acct_auto_close(sb);
shrink_dcache_sb(sb);
sync_filesystem(sb);
- lock_kernel();
/* If we are remounting RDONLY and current sb is read/write,
make sure there are no rw files opened */
if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) {
if (force)
mark_files_ro(sb);
else if (!fs_may_remount_ro(sb)) {
unlock_kernel();
return -EBUSY;
}
retval = vfs_dq_off(sb, 1);
if (retval < 0 && retval != -ENOSYS) {
unlock_kernel();
return -EBUSY;
}
}
remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY);
if (sb->s_op->remount_fs) {
retval = sb->s_op->remount_fs(sb, &flags, data);
if (retval) {
unlock_kernel();
return retval;
}
}
sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
- unlock_kernel();
cheers
> ------------[ cut here ]------------
> kernel BUG at lib/kernel_lock.c:126!
> Oops: Exception in kernel mode, sig: 5 [#1]
> SMP NR_CPUS=1024 NUMA pSeries
> Modules linked in: ipv6 fuse loop dm_mod sr_mod ehea cdrom sg ibmveth sd_mod crc_t10dif ibmvscsic scsi_transport_srp scsi_tgt scsi_mod
> NIP: c0000000005c6dac LR: c0000000001965ac CTR: 0000000000000006
> REGS: c00000002a5d3910 TRAP: 0700 Not tainted (2.6.30-git10)
> MSR: 8000000000029032 <EE,ME,CE,IR,DR> CR: 82042442 XER: 00000000
> TASK = c0000000407cbc20[9581] 'mount' THREAD: c00000002a5d0000 CPU: 3
> <6>GPR00: 0000000000000001 c00000002a5d3b90 c000000000ef31f0 fffffffffffffff0
> <6>GPR04: c0000000000f0098 c000000000799813 0000000000000000 0000000000000001
> <6>GPR08: c000000000e36aa0 c0000000407cbc20 0000000000000002 c0000000407cbc20
> <6>GPR12: 0000000024042424 c000000000ff2a00 00000fffed50f6fd 00000fffed506e08
> <6>GPR16: 00000fffed506db8 000000001002b638 0000000000000000 0000000000000000
> <6>GPR20: 00000000100329a0 00000fffed506e0c c00000003e14b870 0000000000000000
> <6>GPR24: 0000000000000000 c00000002a030000 0000000000000000 0000000000000000
> <6>GPR28: c00000003e14b800 fffffffffffffff0 c000000000e7aa40 c00000002a5d3b90
> NIP [c0000000005c6dac] .unlock_kernel+0x20/0x78
> LR [c0000000001965ac] .do_remount_sb+0x190/0x204
> Call Trace:
> [c00000002a5d3bd0] [c00000000019659c] .do_remount_sb+0x180/0x204
> [c00000002a5d3c70] [c0000000001b8210] .do_mount+0x38c/0x9fc
> [c00000002a5d3d60] [c0000000001b8940] .SyS_mount+0xc0/0x12c
> [c00000002a5d3e30] [c000000000008534] syscall_exit+0x0/0x40
> Instruction dump:
> 383f0040 ebc1fff0 ebe1fff8 4e800020 fbc1fff0 fbe1fff8 f821ffc1 7c3f0b78
> ebc2c0b8 e92d01b0 e809001e 78000fe0 <0b000000> e96d01b0 812b001c 3929ffff
> ---[ end trace 3bf0012ad33d52b2 ]---
>
> Corresponding c code is :
>
> void __lockfunc unlock_kernel(void)
> {
> BUG_ON(current->lock_depth < 0); <<======
> if (likely(--current->lock_depth < 0))
> __unlock_kernel();
>
> Have attached the cgroups regression test run log.
>
> Thanks
> -Sachin
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply related
* Re: MPC83xx watchdog reset board dead lock
From: Leon Woestenberg @ 2009-06-17 11:07 UTC (permalink / raw)
To: Norbert van Bolhuis; +Cc: Linux PPC
In-Reply-To: <c384c5ea0906170309j6fdf28f5qc38129e82649ef28@mail.gmail.com>
Hello,
On Wed, Jun 17, 2009 at 12:09 PM, Leon
Woestenberg<leon.woestenberg@gmail.com> wrote:
> Quoting David Hawkins, who gave a very clear explanation:
> <...>
> If you have the Flash BUSY# signal, then this scheme works
> great, since using HRESET# low and BUSY# low to create a
> PORESET# source is only active until the Flash RESET#
> is asserted long enough for it to get out of the BUSY#
> state and back into read-array mode.
>
I just found out from a Spansion datasheet that the RY/BUSY# of a
typical Flash NOR is enabled by CE#, and tri-state otherwise.
CE# in turn is driven by the LCS# from the PowerPC.
So basically, the first configuration access cycle while the NOR is in
write mode, will pull CE# low, which results in RY/BUSY#
being driven.
I have measured this pulse is ~1.9 us. So the reset circuitry needs a
maximum minimum pulse duration of 1.9 us.
Our reset controller (DS1818) fulfills this requirement, with a T,PB of 1 us.
A reset controller will extend the reset pulse. This is needed because:
for Flash NOR: I have seen a mininum of 35 us reset pulse.
(for the PowerPC: PORESET# should be asserted externally for at least
32 input clock cycles)
Regards,
--
Leon
^ permalink raw reply
* [BUG] lib/kernel_lock.c:126 with cgroups regression ltp tests
From: Sachin Sant @ 2009-06-17 10:51 UTC (permalink / raw)
To: linux-kernel; +Cc: linuxppc-dev, menage, Balbir Singh
[-- Attachment #1: Type: text/plain, Size: 2356 bytes --]
While executing cgroups regression tests from LTP May 2009
release on a Power6 box came across the following bug.
This is with 2.6.30-git10 (300df7dc89cc276377fc020704e34875d5c473b6)
------------[ cut here ]------------
kernel BUG at lib/kernel_lock.c:126!
Oops: Exception in kernel mode, sig: 5 [#1]
SMP NR_CPUS=1024 NUMA pSeries
Modules linked in: ipv6 fuse loop dm_mod sr_mod ehea cdrom sg ibmveth sd_mod crc_t10dif ibmvscsic scsi_transport_srp scsi_tgt scsi_mod
NIP: c0000000005c6dac LR: c0000000001965ac CTR: 0000000000000006
REGS: c00000002a5d3910 TRAP: 0700 Not tainted (2.6.30-git10)
MSR: 8000000000029032 <EE,ME,CE,IR,DR> CR: 82042442 XER: 00000000
TASK = c0000000407cbc20[9581] 'mount' THREAD: c00000002a5d0000 CPU: 3
<6>GPR00: 0000000000000001 c00000002a5d3b90 c000000000ef31f0 fffffffffffffff0
<6>GPR04: c0000000000f0098 c000000000799813 0000000000000000 0000000000000001
<6>GPR08: c000000000e36aa0 c0000000407cbc20 0000000000000002 c0000000407cbc20
<6>GPR12: 0000000024042424 c000000000ff2a00 00000fffed50f6fd 00000fffed506e08
<6>GPR16: 00000fffed506db8 000000001002b638 0000000000000000 0000000000000000
<6>GPR20: 00000000100329a0 00000fffed506e0c c00000003e14b870 0000000000000000
<6>GPR24: 0000000000000000 c00000002a030000 0000000000000000 0000000000000000
<6>GPR28: c00000003e14b800 fffffffffffffff0 c000000000e7aa40 c00000002a5d3b90
NIP [c0000000005c6dac] .unlock_kernel+0x20/0x78
LR [c0000000001965ac] .do_remount_sb+0x190/0x204
Call Trace:
[c00000002a5d3bd0] [c00000000019659c] .do_remount_sb+0x180/0x204
[c00000002a5d3c70] [c0000000001b8210] .do_mount+0x38c/0x9fc
[c00000002a5d3d60] [c0000000001b8940] .SyS_mount+0xc0/0x12c
[c00000002a5d3e30] [c000000000008534] syscall_exit+0x0/0x40
Instruction dump:
383f0040 ebc1fff0 ebe1fff8 4e800020 fbc1fff0 fbe1fff8 f821ffc1 7c3f0b78
ebc2c0b8 e92d01b0 e809001e 78000fe0 <0b000000> e96d01b0 812b001c 3929ffff
---[ end trace 3bf0012ad33d52b2 ]---
Corresponding c code is :
void __lockfunc unlock_kernel(void)
{
BUG_ON(current->lock_depth < 0); <<======
if (likely(--current->lock_depth < 0))
__unlock_kernel();
Have attached the cgroups regression test run log.
Thanks
-Sachin
--
---------------------------------
Sachin Sant
IBM Linux Technology Center
India Systems and Technology Labs
Bangalore, India
---------------------------------
[-- Attachment #2: controller-run.log --]
[-- Type: text/x-log, Size: 2832 bytes --]
cgroup_regression_test 1 PASS : no kernel bug was found
/ltp-full-20090531/testcases/bin/cgroup_regression_test.sh: line 102: 7036 Terminated ./fork_processes
cgroup_regression_test 2 PASS : notify_on_release is inherited
cgroup_regression_test 3 PASS : no kernel bug was found
cgroup_regression_test 4 CONF : CONFIG_LOCKDEP is not enabled
cgroup_regression_test 5 PASS : no kernel bug was found
/ltp-full-20090531/testcases/bin/cgroup_regression_test.sh: line 253: 8781 Terminated sleep 100
/ltp-full-20090531/testcases/bin/cgroup_regression_test.sh: line 325: 8800 Terminated ./test_6_2
cgroup_regression_test 6 PASS : no kernel bug was found
------------[ cut here ]------------
Oops: Exception in kernel mode, sig: 5 [#1]
SMP NR_CPUS=1024 NUMA pSeries
Modules linked in: ipv6 fuse loop dm_mod sr_mod ehea cdrom sg ibmveth sd_mod crc_t10dif ibmvscsic scsi_transport_srp scsi_tgt scsi_mod
NIP: c0000000005c6dac LR: c0000000001965ac CTR: 0000000000000006
REGS: c00000002a5d3910 TRAP: 0700 Not tainted (2.6.30-git10)
MSR: 8000000000029032 <EE,ME,CE,IR,DR> CR: 82042442 XER: 00000000
TASK = c0000000407cbc20[9581] 'mount' THREAD: c00000002a5d0000 CPU: 3
<6>GPR00: 0000000000000001 c00000002a5d3b90 c000000000ef31f0 fffffffffffffff0
<6>GPR04: c0000000000f0098 c000000000799813 0000000000000000 0000000000000001
<6>GPR08: c000000000e36aa0 c0000000407cbc20 0000000000000002 c0000000407cbc20
<6>GPR12: 0000000024042424 c000000000ff2a00 00000fffed50f6fd 00000fffed506e08
<6>GPR16: 00000fffed506db8 000000001002b638 0000000000000000 0000000000000000
<6>GPR20: 00000000100329a0 00000fffed506e0c c00000003e14b870 0000000000000000
<6>GPR24: 0000000000000000 c00000002a030000 0000000000000000 0000000000000000
<6>GPR28: c00000003e14b800 fffffffffffffff0 c000000000e7aa40 c00000002a5d3b90
NIP [c0000000005c6dac] .unlock_kernel+0x20/0x78
LR [c0000000001965ac] .do_remount_sb+0x190/0x204
Call Trace:
[c00000002a5d3bd0] [c00000000019659c] .do_remount_sb+0x180/0x204
[c00000002a5d3c70] [c0000000001b8210] .do_mount+0x38c/0x9fc
[c00000002a5d3d60] [c0000000001b8940] .SyS_mount+0xc0/0x12c
[c00000002a5d3e30] [c000000000008534] syscall_exit+0x0/0x40
Instruction dump:
383f0040 ebc1fff0 ebe1fff8 4e800020 fbc1fff0 fbe1fff8 f821ffc1 7c3f0b78
ebc2c0b8 e92d01b0 e809001e 78000fe0 <0b000000> e96d01b0 812b001c 3929ffff
---[ end trace 3bf0012ad33d52b2 ]---
/ltp-full-20090531/testcases/bin/cgroup_regression_test.sh: line 347: 9581 Trace/breakpoint trap mount -t cgroup -o remount xxx cgroup/ 2> /dev/null
/ltp-full-20090531/testcases/bin/cgroup_regression_test.sh: line 363: 9579 Terminated sleep 100 < cgroup/0
Cannot create link /etc/mtab~
Perhaps there is a stale lock file?
Cannot create link /etc/mtab~
Perhaps there is a stale lock file?
^ permalink raw reply
* Re: [PATCH] powerpc/mm: Fix potential access to freed pages when using hugetlbfs
From: Benjamin Herrenschmidt @ 2009-06-17 10:11 UTC (permalink / raw)
To: Sachin Sant; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <4A38B4EA.20507@in.ibm.com>
> Thanks for the patch. The machine survived after two days of
> testing with hugetlbfs tests.
Excellent, thanks for testing, I'll merge it with my next batch.
Cheers,
Ben.
^ permalink raw reply
* Re: MPC83xx watchdog reset board dead lock
From: Leon Woestenberg @ 2009-06-17 10:09 UTC (permalink / raw)
To: Norbert van Bolhuis; +Cc: Linux PPC
In-Reply-To: <4A38AADD.3070801@aimvalley.nl>
Hello all,
On Wed, Jun 17, 2009 at 10:35 AM, Norbert van
Bolhuis<nvbolhuis@aimvalley.nl> wrote:
> Hi Leon,
>
> I doubt if there are working designs for this.
> ...
> In u-boot the watchdog (if enabled with CONFIG_WATCHDOG) is normally
> strobed in the decrementer interrupt routine (timer_interrupt). So
> I guess there's not a big chance it triggers a reset.
> ...
>
Most designs do not care about the watchdog, or only pet in their
non-critical paths... That's not what the watchdog is for.
Also, I don't care about u-boot.
I care about a design where the Flash NOR could be in write mode at
any time when the watchdog triggers, when the hardware is running
critical software.
No lifes in danger when it happens, only jobs, so no biggy :-)
David has been helpful in thinking this through, but we followed-up
offline, and we independently came up with the following design, so
this must therefore work (disclaimer applies).
Note, it DOES require a NOR flash that has a RY/BUSY# pin.
Quoting David Hawkins, who gave a very clear explanation:
---
How about using the RDY/BUSY# pin on the Flash in conjunction
with PORESET#. If the flash is busy, then the processor gets
PORESET#, otherwise, the HRESET# just does its normal thing.
That way PORESET# only ever asserts when you have the
combo of the Flash being busy and HRESET# asserting.
<...>
If you have the Flash BUSY# signal, then this scheme works
great, since using HRESET# low and BUSY# low to create a
PORESET# source is only active until the Flash RESET#
is asserted long enough for it to get out of the BUSY#
state and back into read-array mode.
---
Kudos to David.
I'll be testing the design tomorrow on the reference board, I'll
report results in this thread.
Regards / Groeten,
--
Leon
^ permalink raw reply
* 8xx: 2.4.25, fec.c, consistent_alloc and eth_copy_and_sum
From: Joerg Albert @ 2009-06-17 9:49 UTC (permalink / raw)
To: linuxppc-dev
Looking into arch/ppc/8xx_io/fec.c in the linuxppc_2_4_devel git tree I wonder if it is necessary to copy every received frame from memory allocated by consistent_alloc into a socket buffer? Couldn't we let the FEC
DMA directly into the socket buffer to improve the performance?
BTW, has someone tried to implement NAPI in this driver?
Regards,
Joerg
--
GMX FreeDSL Komplettanschluss mit DSL 6.000 Flatrate und Telefonanschluss
für nur 17,95 Euro/mtl.!* http://portal.gmx.net/de/go/dsl02
^ permalink raw reply
* Re: sym scsi driver problem with 2.6.26 or newer debian kernel on p610 (fwd)
From: Laszlo Fekete @ 2009-06-17 9:33 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: linuxppc-dev, debian-powerpc
In-Reply-To: <Pine.LNX.4.64.0906141105050.4412@axis700.grange>
Hello!
I'm sorry about the annoyances, but I'd welcome all ideas, suggestions
to see what needs to be done or should be tested for the solution.
Thank you very much!
Guennadi Liakhovetski wrote:
> Ok, first attempt to forward this to scsi was wrong, as pointed out by
> Matthew Wilcox this does indeed look like an interrupt problem - no
> interrupts drom SCSI, IDE, keyboar. Might be a known problem, I guess. In
> any case, I think, the OP would be grateful for any hints.
>
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> http://www.open-technology.de/
>
> ---------- Forwarded message ----------
> Date: Sat, 13 Jun 2009 16:22:07 +0200
> From: Laszlo Fekete <blackluck@ktk.bme.hu>
> To: debian-powerpc@lists.debian.org
> Subject: sym scsi driver problem with 2.6.26 or newer debian kernel on p610
> Resent-Date: Sat, 13 Jun 2009 14:29:55 +0000 (UTC)
> Resent-From: debian-powerpc@lists.debian.org
>
> This is a multi-part message in MIME format.
> ------------------------------------------------------------------------
>
> Hello!
>
>
>
>
>
> Pls help me with sym scsi driver problem.
>
>
>
> I have Ibm P610 (and tested it on P630 and P640 too), installed debian
>
> etch and upgraded to lenny.
>
>
>
> But with 2.6.26 or newer kernel it's not booting, it's hang on sym scsi
>
> bus scan.
>
>
>
>
>
> Whats the problem with it, or how can I fix this?
>
>
>
>
>
> I attach the output from minicom with 2.6.29, 2.6.26, and the working
>
> 2.6.24 kernel booting.
>
>
>
>
>
> Thank you very much!
>
>
>
^ permalink raw reply
* Re: [PATCH] powerpc/mm: Fix potential access to freed pages when using hugetlbfs
From: Sachin Sant @ 2009-06-17 9:18 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20090616025419.A5581DDD1B@ozlabs.org>
Benjamin Herrenschmidt wrote:
> When using 64k page sizes, our PTE pages are split in two halves,
> the second half containing the "extension" used to keep track of
> individual 4k pages when not using HW 64k pages.
>
> However, our page tables used for hugetlb have a slightly different
> format and don't carry that "second half".
>
> Our code that batched PTEs to be invalidated unconditionally reads
> the "second half" (to put it into the batch), which means that when
> called to invalidate hugetlb PTEs, it will access unrelated memory.
>
> It breaks when CONFIG_DEBUG_PAGEALLOC is enabled.
>
> This fixes it by only accessing the second half when the _PAGE_COMBO
> bit is set in the first half, which indicates that we are dealing with
> a "combo" page which represents 16x4k subpages. Anything else shouldn't
> have this bit set and thus not require loading from the second half.
>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Thanks for the patch. The machine survived after two days of
testing with hugetlbfs tests.
Regards
-Sachin
--
---------------------------------
Sachin Sant
IBM Linux Technology Center
India Systems and Technology Labs
Bangalore, India
---------------------------------
^ permalink raw reply
* [PATCH] powerpc: Add irqtrace support for 32-bit powerpc
From: Benjamin Herrenschmidt @ 2009-06-17 9:01 UTC (permalink / raw)
To: linuxppc-dev
Based on initial work from: Dale Farnsworth <dale@farnsworth.org>
Add the low level irq tracing hooks for 32-bit powerpc needed
to enable full lockdep functionality.
The approach taken to deal with the code in entry_32.S is that
we don't trace all the transitions of MSR:EE when we just turn
it off to peek at TI_FLAGS without races. Only when we are
calling into C code or returning from exceptions with a state
that have changed from what lockdep thinks.
There's a little bugger though: If we take an exception that
keeps interrupts enabled (such as an alignment exception) while
interrupts are enabled, we will call trace_hardirqs_on() on the
way back spurriously. Not a big deal, but to get rid of it would
require remembering in pt_regs that the exception was one of the
type that kept interrupts enabled which we don't know at this
stage. (Well, we could test all cases for regs->trap but that
sucks too much).
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Not very well tested ... got issues with my u-boot on the 440
board and I didn't have much time to test elsewhere. FSL welcome
to test on funky configs. It's likely to still be subtely broken :-)
arch/powerpc/Kconfig | 1
arch/powerpc/include/asm/hw_irq.h | 20 +++---
arch/powerpc/kernel/entry_32.S | 126 ++++++++++++++++++++++++++++++++++++--
arch/powerpc/kernel/setup_32.c | 2
arch/powerpc/kernel/udbg.c | 1
5 files changed, 135 insertions(+), 15 deletions(-)
--- linux-work.orig/arch/powerpc/Kconfig 2009-06-17 16:45:15.000000000 +1000
+++ linux-work/arch/powerpc/Kconfig 2009-06-17 16:45:36.000000000 +1000
@@ -62,7 +62,6 @@ config HAVE_LATENCYTOP_SUPPORT
config TRACE_IRQFLAGS_SUPPORT
bool
- depends on PPC64
default y
config LOCKDEP_SUPPORT
Index: linux-work/arch/powerpc/kernel/entry_32.S
===================================================================
--- linux-work.orig/arch/powerpc/kernel/entry_32.S 2009-06-17 16:45:15.000000000 +1000
+++ linux-work/arch/powerpc/kernel/entry_32.S 2009-06-17 18:29:23.000000000 +1000
@@ -191,11 +191,49 @@ transfer_to_handler_cont:
mflr r9
lwz r11,0(r9) /* virtual address of handler */
lwz r9,4(r9) /* where to go when done */
+#ifdef CONFIG_TRACE_IRQFLAGS
+ lis r12,reenable_mmu@h
+ ori r12,r12,reenable_mmu@l
+ mtspr SPRN_SRR0,r12
+ mtspr SPRN_SRR1,r10
+ SYNC
+ RFI
+reenable_mmu: /* re-enable mmu so we can */
+ mfmsr r10
+ lwz r12,_MSR(r1)
+ xor r10,r10,r12
+ andi. r10,r10,MSR_EE /* Did EE change? */
+ beq 1f
+
+ /* Save handler and return address into the 2 unused words
+ * of the STACK_FRAME_OVERHEAD (sneak sneak sneak). Everything
+ * else can be recovered from the pt_regs except r3 which for
+ * normal interrupts has been set to pt_regs and for syscalls
+ * is an argument, so we temporarily use ORIG_GPR3 to save it
+ */
+ stw r9,8(r1)
+ stw r11,12(r1)
+ stw r3,ORIG_GPR3(r1)
+ bl trace_hardirqs_off
+ lwz r0,GPR0(r1)
+ lwz r3,ORIG_GPR3(r1)
+ lwz r4,GPR4(r1)
+ lwz r5,GPR5(r1)
+ lwz r6,GPR6(r1)
+ lwz r7,GPR7(r1)
+ lwz r8,GPR8(r1)
+ lwz r9,8(r1)
+ lwz r11,12(r1)
+1: mtctr r11
+ mtlr r9
+ bctr /* jump to handler */
+#else /* CONFIG_TRACE_IRQFLAGS */
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r10
mtlr r9
SYNC
RFI /* jump to handler, enable MMU */
+#endif /* CONFIG_TRACE_IRQFLAGS */
#if defined (CONFIG_6xx) || defined(CONFIG_E500)
4: rlwinm r12,r12,0,~_TLF_NAPPING
@@ -251,6 +289,31 @@ _GLOBAL(DoSyscall)
#ifdef SHOW_SYSCALLS
bl do_show_syscall
#endif /* SHOW_SYSCALLS */
+#ifdef CONFIG_TRACE_IRQFLAGS
+ /* Return from syscalls can (and generally will) hard enable
+ * interrupts. You aren't supposed to call a syscall with
+ * interrupts disabled in the first place. However, to ensure
+ * that we get it right vs. lockdep if it happens, we force
+ * that hard enable here with appropriate tracing if we see
+ * that we have been called with interrupts off
+ */
+ mfmsr r11
+ andi. r12,r11,MSR_EE
+ bne+ 1f
+ /* We came in with interrupts disabled, we enable them now */
+ bl trace_hardirqs_on
+ mfmsr r11
+ lwz r0,GPR0(r1)
+ lwz r3,GPR3(r1)
+ lwz r4,GPR4(r1)
+ ori r11,r11,MSR_EE
+ lwz r5,GPR5(r1)
+ lwz r6,GPR6(r1)
+ lwz r7,GPR7(r1)
+ lwz r8,GPR8(r1)
+ mtmsr r11
+1:
+#endif /* CONFIG_TRACE_IRQFLAGS */
rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
lwz r11,TI_FLAGS(r10)
andi. r11,r11,_TIF_SYSCALL_T_OR_A
@@ -275,6 +338,7 @@ ret_from_syscall:
rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
/* disable interrupts so current_thread_info()->flags can't change */
LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
+ /* Note: We don't bother telling lockdep about it */
SYNC
MTMSRD(r10)
lwz r9,TI_FLAGS(r12)
@@ -288,6 +352,19 @@ ret_from_syscall:
oris r11,r11,0x1000 /* Set SO bit in CR */
stw r11,_CCR(r1)
syscall_exit_cont:
+ lwz r8,_MSR(r1)
+#ifdef CONFIG_TRACE_IRQFLAGS
+ /* If we are going to return from the syscall with interrupts
+ * off, we trace that here. It shouldn't happen though but we
+ * want to catch the bugger if it does right ?
+ */
+ andi. r10,r8,MSR_EE
+ bne+ 1f
+ stw r3,GPR3(r1)
+ bl trace_hardirqs_off
+ lwz r3,GPR3(r1)
+1:
+#endif /* CONFIG_TRACE_IRQFLAGS */
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
/* If the process has its own DBCR0 value, load it up. The internal
debug mode bit tells us that dbcr0 should be loaded. */
@@ -311,7 +388,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRE
mtlr r4
mtcr r5
lwz r7,_NIP(r1)
- lwz r8,_MSR(r1)
FIX_SRR1(r8, r0)
lwz r2,GPR2(r1)
lwz r1,GPR1(r1)
@@ -394,7 +470,9 @@ syscall_exit_work:
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
beq ret_from_except
- /* Re-enable interrupts */
+ /* Re-enable interrupts. There is no need to trace that with
+ * lockdep as we are supposed to have IRQs on at this point
+ */
ori r10,r10,MSR_EE
SYNC
MTMSRD(r10)
@@ -705,6 +783,7 @@ ret_from_except:
/* Hard-disable interrupts so that current_thread_info()->flags
* can't change between when we test it and when we return
* from the interrupt. */
+ /* Note: We don't bother telling lockdep about it */
LOAD_MSR_KERNEL(r10,MSR_KERNEL)
SYNC /* Some chip revs have problems here... */
MTMSRD(r10) /* disable interrupts */
@@ -744,11 +823,24 @@ resume_kernel:
beq+ restore
andi. r0,r3,MSR_EE /* interrupts off? */
beq restore /* don't schedule if so */
+#ifdef CONFIG_TRACE_IRQFLAGS
+ /* Lockdep thinks irqs are enabled, we need to call
+ * preempt_schedule_irq with IRQs off, so we inform lockdep
+ * now that we -did- turn them off already
+ */
+ bl trace_hardirqs_off
+#endif
1: bl preempt_schedule_irq
rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
lwz r3,TI_FLAGS(r9)
andi. r0,r3,_TIF_NEED_RESCHED
bne- 1b
+#ifdef CONFIG_TRACE_IRQFLAGS
+ /* And now, to properly rebalance the above, we tell lockdep they
+ * are being turned back on, which will happen when we return
+ */
+ bl trace_hardirqs_on
+#endif
#else
resume_kernel:
#endif /* CONFIG_PREEMPT */
@@ -781,8 +873,28 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
stwcx. r0,0,r1 /* to clear the reservation */
-#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
lwz r9,_MSR(r1)
+#ifdef CONFIG_TRACE_IRQFLAGS
+ /* Lockdep doesn't know about the fact that IRQs are temporarily turned
+ * off in this assembly code while peeking at TI_FLAGS() and such. However
+ * we need to inform it if the exception turned interrupts off, and we
+ * are about to trun them back on.
+ *
+ * The problem here sadly is that we don't know whether the exceptions was
+ * one that turned interrupts off or not. So we always tell lockdep about
+ * turning them on here when we go back to wherever we came from with EE
+ * on, even if that may meen some redudant calls being tracked. Maybe later
+ * we could encode what the exception did somewhere or test the exception
+ * type in the pt_regs but that sounds overkill
+ */
+ andi. r10,r9,MSR_EE
+ beq 1f
+ bl trace_hardirqs_on
+ lwz r9,_MSR(r1)
+1:
+#endif /* CONFIG_TRACE_IRQFLAGS */
+
+#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
andi. r10,r9,MSR_RI /* check if this exception occurred */
beql nonrecoverable /* at a bad place (MSR:RI = 0) */
@@ -805,7 +917,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRE
MTMSRD(r10) /* clear the RI bit */
.globl exc_exit_restart
exc_exit_restart:
- lwz r9,_MSR(r1)
lwz r12,_NIP(r1)
FIX_SRR1(r9,r10)
mtspr SPRN_SRR0,r12
@@ -1035,11 +1146,18 @@ do_work: /* r10 contains MSR_KERNEL he
beq do_user_signal
do_resched: /* r10 contains MSR_KERNEL here */
+ /* Note: We don't need to inform lockdep that we are enabling
+ * interrupts here. As far as it knows, they are already enabled
+ */
ori r10,r10,MSR_EE
SYNC
MTMSRD(r10) /* hard-enable interrupts */
bl schedule
recheck:
+ /* Note: And we don't tell it we are disabling them again
+ * neither. Those disable/enable cycles used to peek at
+ * TI_FLAGS aren't advertised.
+ */
LOAD_MSR_KERNEL(r10,MSR_KERNEL)
SYNC
MTMSRD(r10) /* disable interrupts */
Index: linux-work/arch/powerpc/kernel/setup_32.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/setup_32.c 2009-06-17 16:45:15.000000000 +1000
+++ linux-work/arch/powerpc/kernel/setup_32.c 2009-06-17 18:29:37.000000000 +1000
@@ -119,6 +119,8 @@ notrace unsigned long __init early_init(
*/
notrace void __init machine_init(unsigned long dt_ptr)
{
+ lockdep_init();
+
/* Enable early debugging if any specified (see udbg.h) */
udbg_early_init();
Index: linux-work/arch/powerpc/include/asm/hw_irq.h
===================================================================
--- linux-work.orig/arch/powerpc/include/asm/hw_irq.h 2009-06-17 16:45:15.000000000 +1000
+++ linux-work/arch/powerpc/include/asm/hw_irq.h 2009-06-17 16:45:36.000000000 +1000
@@ -68,13 +68,13 @@ static inline int irqs_disabled_flags(un
#if defined(CONFIG_BOOKE)
#define SET_MSR_EE(x) mtmsr(x)
-#define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
+#define raw_local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
#else
#define SET_MSR_EE(x) mtmsr(x)
-#define local_irq_restore(flags) mtmsr(flags)
+#define raw_local_irq_restore(flags) mtmsr(flags)
#endif
-static inline void local_irq_disable(void)
+static inline void raw_local_irq_disable(void)
{
#ifdef CONFIG_BOOKE
__asm__ __volatile__("wrteei 0": : :"memory");
@@ -86,7 +86,7 @@ static inline void local_irq_disable(voi
#endif
}
-static inline void local_irq_enable(void)
+static inline void raw_local_irq_enable(void)
{
#ifdef CONFIG_BOOKE
__asm__ __volatile__("wrteei 1": : :"memory");
@@ -98,7 +98,7 @@ static inline void local_irq_enable(void
#endif
}
-static inline void local_irq_save_ptr(unsigned long *flags)
+static inline void raw_local_irq_save_ptr(unsigned long *flags)
{
unsigned long msr;
msr = mfmsr();
@@ -110,12 +110,12 @@ static inline void local_irq_save_ptr(un
#endif
}
-#define local_save_flags(flags) ((flags) = mfmsr())
-#define local_irq_save(flags) local_irq_save_ptr(&flags)
-#define irqs_disabled() ((mfmsr() & MSR_EE) == 0)
+#define raw_local_save_flags(flags) ((flags) = mfmsr())
+#define raw_local_irq_save(flags) raw_local_irq_save_ptr(&flags)
+#define raw_irqs_disabled() ((mfmsr() & MSR_EE) == 0)
+#define raw_irqs_disabled_flags(flags) (((flags) & MSR_EE) == 0)
-#define hard_irq_enable() local_irq_enable()
-#define hard_irq_disable() local_irq_disable()
+#define hard_irq_disable() raw_local_irq_disable()
static inline int irqs_disabled_flags(unsigned long flags)
{
Index: linux-work/arch/powerpc/kernel/udbg.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/udbg.c 2009-06-17 17:14:41.000000000 +1000
+++ linux-work/arch/powerpc/kernel/udbg.c 2009-06-17 17:14:43.000000000 +1000
@@ -65,6 +65,7 @@ void __init udbg_early_init(void)
#ifdef CONFIG_PPC_EARLY_DEBUG
console_loglevel = 10;
#endif
+ register_early_udbg_console();
}
/* udbg library, used by xmon et al */
^ permalink raw reply
* Re: MPC83xx watchdog reset board dead lock
From: Norbert van Bolhuis @ 2009-06-17 8:35 UTC (permalink / raw)
To: Leon Woestenberg; +Cc: Linux PPC
In-Reply-To: <c384c5ea0906160852l4845760cp8594463a866683dc@mail.gmail.com>
Hi Leon,
I doubt if there are working designs for this.
In u-boot the watchdog (if enabled with CONFIG_WATCHDOG) is normally
strobed in the decrementer interrupt routine (timer_interrupt). So
I guess there's not a big chance it triggers a reset.
It is possible to configure the WD to issue a machine check interrupt
(i.s.o. HRESET). Maybe it's possible (or even done already) to put the
flash into READ-mode from the isr ?
---
N. van Bolhuis.
Leon Woestenberg wrote:
> Hello,
>
> this is a hardware, even board issue, but I hope to find the right
> target audience here.
>
>
> In our MPC83xx design I would like to prevent dead lock in case where
> a field upgrade is performed, i.e. NOR Flash is erased or written, and
> the MPC83xx built-in hardware watchdog triggers.
>
> In u-boot the scenario can be easily reproduced by running this
> command (WARNING, erases some sectors!) on an MPC8313E-RDB:
>
> erase_wdg=mw.l 0xe0000204 0x10000007 1;mw.w 0xe000020e 0x556c 1;mw.w
> 0xe000020e 0xaa39 1;erase 1:10-30
>
> This sets up the watchdog to reset soonish, then starts erasing NOR
> sectors. Watchdog triggers and resets -> Dead lock.
>
>
> Most MPC8xxx board designs I have seen suffer from this possible dead lock:
> - NOR Flash is put in erase mode or write mode
> - Hardware watchdog triggers
> - HRESET# is asserted by the processor, during which the configuration
> words are read from NOR Flash.
>
> Either
> HRESET# is not attached to NOR, NOR stays in erase/write mode and
> invalid words will be read -> dead lock
>
> or either:
> HRESET# is attached to NOR reset, NOR is reset, but stays in reset as
> HRESET# stays asserted.
>
>
>
> We have been looking at several solutions hardware wise that reset the
> NOR flash on HRESET# going low, but the processors are stubborn,
> read the config words only once, than dead lock.
>
> I wonder if there are known-working designs for this.
>
> Regards,
^ permalink raw reply
* Re: PowerPC PCI DMA issues (prefetch/coherency?)
From: Chris Pringle @ 2009-06-17 7:58 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev@ozlabs.org list, linux-kernel
In-Reply-To: <4A37D073.6020802@freescale.com>
> You could enable CONFIG_NOT_COHERENT_CACHE.
>
I've just tried this (I had to edit Kconfig in power/platforms to make
the build system accept it), and interestingly it's making no
difference. I'm using streaming mappings, and are using the pci_map_sg
functions to ensure the memory is mapped/flushed correctly. I've also
explicitly put in a pci_dma_sync_sg_for_device, however that's also not
made any difference. Turning the cpu cache snoop off has the same affect
as it did without CONFIG_NOT_COHERENT_CACHE; it gets much worse. Any
other ideas?
Will back off the low latency patches next, and give 2.6.30 a try - see
if that makes any difference.
--
______________________________
Chris Pringle
Software Engineer
Miranda Technologies Ltd.
Hithercroft Road
Wallingford
Oxfordshire OX10 9DG
UK
Tel. +44 1491 820206
Fax. +44 1491 820001
www.miranda.com
____________________________
Miranda Technologies Limited
Registered in England and Wales CN 02017053
Registered Office: James House, Mere Park, Dedmere Road, Marlow, Bucks, SL7 1FJ
^ permalink raw reply
* Please pull mpc5xxx & virtex merge branch
From: Grant Likely @ 2009-06-17 7:22 UTC (permalink / raw)
To: Benjamin Herrenschmidt, linuxppc-dev; +Cc: Wolfgang Denk
Hi Ben,
Here's the xilinxfb fix plus some outstanding 5xxx changes that I
didn't get to the first time around.
Cheers,
g.
The following changes since commit 313485175da221c388f6a8ecf4c30062ba9bea17:
Geert Uytterhoeven (1):
usb/ps3: Add missing annotations
are available in the git repository at:
git://git.secretlab.ca/git/linux-2.6 merge
Anton Vorontsov (1):
powerpc/5200: convert mpc52xx_psc_spi to use cs_control callback
Grant Likely (1):
fbdev/xilinxfb: Fix improper casting and tighen up probe path
Wolfgang Denk (1):
powerpc/5xxx: Add common mpc5xxx_get_bus_frequency() function
Wolfram Sang (2):
powerpc/5200: Update pcm030.dts to add i2c eeprom and delete cruft
powerpc/5121: make clock debug output more readable
arch/powerpc/boot/dts/pcm030.dts | 26 ++--------
arch/powerpc/include/asm/mpc52xx.h | 2 +-
arch/powerpc/include/asm/{mpc512x.h => mpc5xxx.h} | 10 ++--
arch/powerpc/platforms/512x/clock.c | 10 ++--
arch/powerpc/platforms/512x/mpc512x.h | 1 -
arch/powerpc/platforms/512x/mpc512x_shared.c | 23 --------
arch/powerpc/platforms/52xx/mpc52xx_common.c | 32 +-----------
arch/powerpc/sysdev/Makefile | 3 +
arch/powerpc/sysdev/mpc5xxx_clocks.c | 33 ++++++++++++
drivers/ata/pata_mpc52xx.c | 2 +-
drivers/i2c/busses/i2c-mpc.c | 2 +-
drivers/net/fec_mpc52xx.c | 2 +-
drivers/net/fec_mpc52xx_phy.c | 2 +-
drivers/serial/mpc52xx_uart.c | 5 +-
drivers/spi/mpc52xx_psc_spi.c | 22 +++-----
drivers/video/xilinxfb.c | 59 ++++++++-------------
drivers/watchdog/mpc5200_wdt.c | 2 +-
include/linux/fsl_devices.h | 4 --
18 files changed, 91 insertions(+), 149 deletions(-)
rename arch/powerpc/include/asm/{mpc512x.h => mpc5xxx.h} (65%)
create mode 100644 arch/powerpc/sysdev/mpc5xxx_clocks.c
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [ewg] Re: [PATCH 2.6.31] ehca: Tolerate dynamic memory operations and huge pages
From: Alexander Schmidt @ 2009-06-17 6:41 UTC (permalink / raw)
To: Roland Dreier; +Cc: linuxppc-dev, Hoang-Nam Nguyen, raisch, linux-kernel, ewg
In-Reply-To: <adazlc8w45c.fsf@cisco.com>
On Tue, 16 Jun 2009 09:10:39 -0700
Roland Dreier <rdreier@cisco.com> wrote:
>
> > Yeah, the notifier code remains untouched as we still do not allow dynamic
> > memory operations _while_ our module is loaded. The patch allows the driver to
> > cope with DMEM operations that happened before the module was loaded, which
> > might result in a non-contiguous memory layout. When the driver registers
> > its global memory region in the system, the memory layout must be considered.
> >
> > We chose the term "toleration" instead of "support" to illustrate this.
>
> I see. So things just silently broke in some cases when the driver was
> loaded after operations you didn't tolerate?
>
> Anyway, thanks for the explanation.
Well, things did not break silently. The registration of the MR failed with
an error code which was reported to userspace.
Will you push the patch for .31 or .32?
Thanks,
Alex
^ 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