* powerpc: should mem_end be assigned to dt_struct_end in flatten_device_tree()?
From: Roel Kluin @ 2010-01-14 23:00 UTC (permalink / raw)
To: Paul Mackerras, linuxppc-dev
vi arch/powerpc/kernel/prom_init.c +1961 and note that in
flatten_device_tree() we do a
RELOC(dt_struct_end) = PAGE_ALIGN(mem_start);
should that maybe be
RELOC(dt_struct_end) = PAGE_ALIGN(mem_end);
thanks,
Roel
^ permalink raw reply
* [PATCH 1/2] Add static fields to ibm,client-architecture call
From: Joel Schopp @ 2010-01-14 23:01 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1263501613.4869.139.camel@jschopp-laptop>
This patch adds 2 fields to the ibm_architecture_vec array.
The first of these fields indicates the number of cores which Linux can
boot. It does not account for SMT, so it may result in cpus assigned to
Linux which cannot be booted. A second patch follows that dynamically
updates this for SMT.
The second field just indicates that our OS is Linux, and not another
OS. The system may or may not use this hint to performance tune
settings for Linux.
Sorry if the last version sent out got whitespace munged. Hopefully
evolution works on this one.
Signed-off-by:Joel Schopp<jschopp@austin.ibm.com>
Index: linux-2.6.git/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-2.6.git.orig/arch/powerpc/kernel/prom_init.c
+++ linux-2.6.git/arch/powerpc/kernel/prom_init.c
@@ -654,6 +656,9 @@ static void __init early_cmdline_parse(v
#define OV5_CMO 0x00
#endif
+/* Option Vector 6: IBM PAPR hints */
+#define OV6_LINUX 0x02 /* Linux is our OS */
+
/*
* The architecture vector has an array of PVR mask/value pairs,
* followed by # option vectors - 1, followed by the option vectors.
@@ -665,7 +670,7 @@ static unsigned char ibm_architecture_ve
W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */
W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */
W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
- 5 - 1, /* 5 option vectors */
+ 6 - 1, /* 6 option vectors */
/* option vector 1: processor architectures supported */
3 - 2, /* length */
@@ -697,12 +702,24 @@ static unsigned char ibm_architecture_ve
0, /* don't halt */
/* option vector 5: PAPR/OF options */
- 5 - 2, /* length */
+ 13 - 2, /* length */
0, /* don't ignore, don't halt */
OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
OV5_DONATE_DEDICATE_CPU | OV5_MSI,
0,
OV5_CMO,
+ 0,
+ 0,
+ 0,
+ 0,
+ W(NR_CPUS), /* number of cores supported*/
+
+ /* option vector 6: IBM PAPR hints */
+ 4 - 2, /* length */
+ 0,
+ 0,
+ OV6_LINUX,
+
};
/* Old method - ELF header with PT_NOTE sections */
^ permalink raw reply
* Re: [PATCH] Move cpu hotplug driver lock from pseries to powerpc
From: Michael Ellerman @ 2010-01-14 23:39 UTC (permalink / raw)
To: Nathan Fontenot; +Cc: linuxppc-dev, Andreas Schwab
In-Reply-To: <4B4F760C.4000507@austin.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 584 bytes --]
On Thu, 2010-01-14 at 13:52 -0600, Nathan Fontenot wrote:
> Move the defintion and lock helper routines for the cpu hotplug driver
> lock from pseries to powerpc code to avoid build breaks for platforms
> other than pseries that use cpu hotplug.
>
> Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
> ---
> arch/powerpc/kernel/smp.c | 12 ++++++++++++
> arch/powerpc/platforms/pseries/dlpar.c | 12 ------------
> 2 files changed, 12 insertions(+), 12 deletions(-)
Much nicer :)
Acked-by: Michael Ellerman <michael@ellerman.id.au>
cheers
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: powerpc: should mem_end be assigned to dt_struct_end in flatten_device_tree()?
From: Benjamin Herrenschmidt @ 2010-01-15 2:44 UTC (permalink / raw)
To: Roel Kluin; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <4B4FA225.90108@gmail.com>
On Fri, 2010-01-15 at 00:00 +0100, Roel Kluin wrote:
> vi arch/powerpc/kernel/prom_init.c +1961 and note that in
> flatten_device_tree() we do a
>
> RELOC(dt_struct_end) = PAGE_ALIGN(mem_start);
>
> should that maybe be
>
> RELOC(dt_struct_end) = PAGE_ALIGN(mem_end);
>
Nope.
mem_start is a "cursor", it moves as things gets pushed into the flat
device-tree blob. We thus snapshot its value after pushing the last bit
of the structure. mem_end is just the max boundary past which we can no
longer push things.
Cheers,
Ben.
^ permalink raw reply
* RE: [PATCH 4/4] phy: add RTBI mode for m88e1111
From: Liu Yu-B13201 @ 2010-01-15 2:49 UTC (permalink / raw)
To: Kumar Gala; +Cc: netdev, linuxppc-dev, davem
In-Reply-To: <BC00E67D-5906-4740-A961-84FC1C524A4F@kernel.crashing.org>
=20
> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]=20
> Sent: Friday, January 15, 2010 12:20 AM
> To: Liu Yu-B13201
> Cc: davem@davemloft.net; linuxppc-dev@lists.ozlabs.org;=20
> netdev@vger.kernel.org
> Subject: Re: [PATCH 4/4] phy: add RTBI mode for m88e1111
>=20
>=20
> On Jan 14, 2010, at 2:13 AM, Liu Yu wrote:
>=20
> > Signed-off-by: Liu Yu <yu.liu@freescale.com>
> > ---
> > drivers/net/phy/marvell.c | 38=20
> ++++++++++++++++++++++++++++++++++++++
> > 1 files changed, 38 insertions(+), 0 deletions(-)
> >=20
> > diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
> > index 6f69b9b..65ed385 100644
> > --- a/drivers/net/phy/marvell.c
> > +++ b/drivers/net/phy/marvell.c
> > @@ -63,6 +63,7 @@
> > #define MII_M1111_HWCFG_MODE_COPPER_RGMII 0xb
> > #define MII_M1111_HWCFG_MODE_FIBER_RGMII 0x3
> > #define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4
> > +#define MII_M1111_HWCFG_MODE_COPPER_RTBI 0x9
> > #define MII_M1111_HWCFG_FIBER_COPPER_AUTO 0x8000
> > #define MII_M1111_HWCFG_FIBER_COPPER_RES 0x2000
> >=20
> > @@ -269,6 +270,43 @@ static int m88e1111_config_init(struct=20
> phy_device *phydev)
> > return err;
> > }
> >=20
> > + if (phydev->interface =3D=3D PHY_INTERFACE_MODE_RTBI) {
> > + temp =3D phy_read(phydev, MII_M1111_PHY_EXT_CR);
> > + if (temp < 0)
> > + return temp;
> > + temp |=3D (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
> > + err =3D phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
> > + if (err < 0)
> > + return err;
> > +
> > + temp =3D phy_read(phydev, MII_M1111_PHY_EXT_SR);
> > + if (temp < 0)
> > + return temp;
> > + temp &=3D ~(MII_M1111_HWCFG_MODE_MASK |=20
> MII_M1111_HWCFG_FIBER_COPPER_RES);
> > + temp |=3D 0x7 | MII_M1111_HWCFG_FIBER_COPPER_AUTO;
>=20
> Does this magic 0x7 have some meaning?
>=20
Hrr... it's GMII to fibre mode.
Document 88E1111_erata_RevB2 chapter 4.35 describ the reason.
Without this sometimes phys couldnot work.
^ permalink raw reply
* Re: [PATCH 1/2] Add static fields to ibm,client-architecture call
From: Benjamin Herrenschmidt @ 2010-01-15 2:51 UTC (permalink / raw)
To: Joel Schopp; +Cc: linuxppc-dev
In-Reply-To: <1263510116.7445.5.camel@jschopp-laptop>
On Thu, 2010-01-14 at 17:01 -0600, Joel Schopp wrote:
> This patch adds 2 fields to the ibm_architecture_vec array.
>
> The first of these fields indicates the number of cores which Linux can
> boot. It does not account for SMT, so it may result in cpus assigned to
> Linux which cannot be booted. A second patch follows that dynamically
> updates this for SMT.
>
> The second field just indicates that our OS is Linux, and not another
> OS. The system may or may not use this hint to performance tune
> settings for Linux.
Patch submission 101...
> Sorry if the last version sent out got whitespace munged. Hopefully
> evolution works on this one.
The above should be past the signature marker (--) so it doesn't end up
in the changeset comments
> Signed-off-by:Joel Schopp<jschopp@austin.ibm.com>
The marker should be here or the line below:
> Index: linux-2.6.git/arch/powerpc/kernel/prom_init.c
> ===================================================================
Would also end up in the comments.
The rest looks fine.
Cheers,
Ben.
> --- linux-2.6.git.orig/arch/powerpc/kernel/prom_init.c
> +++ linux-2.6.git/arch/powerpc/kernel/prom_init.c
> @@ -654,6 +656,9 @@ static void __init early_cmdline_parse(v
> #define OV5_CMO 0x00
> #endif
>
> +/* Option Vector 6: IBM PAPR hints */
> +#define OV6_LINUX 0x02 /* Linux is our OS */
> +
> /*
> * The architecture vector has an array of PVR mask/value pairs,
> * followed by # option vectors - 1, followed by the option vectors.
> @@ -665,7 +670,7 @@ static unsigned char ibm_architecture_ve
> W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */
> W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */
> W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
> - 5 - 1, /* 5 option vectors */
> + 6 - 1, /* 6 option vectors */
>
> /* option vector 1: processor architectures supported */
> 3 - 2, /* length */
> @@ -697,12 +702,24 @@ static unsigned char ibm_architecture_ve
> 0, /* don't halt */
>
> /* option vector 5: PAPR/OF options */
> - 5 - 2, /* length */
> + 13 - 2, /* length */
> 0, /* don't ignore, don't halt */
> OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
> OV5_DONATE_DEDICATE_CPU | OV5_MSI,
> 0,
> OV5_CMO,
> + 0,
> + 0,
> + 0,
> + 0,
> + W(NR_CPUS), /* number of cores supported*/
> +
> + /* option vector 6: IBM PAPR hints */
> + 4 - 2, /* length */
> + 0,
> + 0,
> + OV6_LINUX,
> +
> };
>
> /* Old method - ELF header with PT_NOTE sections */
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 1/2] Add static fields to ibm,client-architecture call
From: Benjamin Herrenschmidt @ 2010-01-15 2:52 UTC (permalink / raw)
To: Joel Schopp; +Cc: linuxppc-dev
In-Reply-To: <1263523863.724.380.camel@pasglop>
Oh and :
> > Signed-off-by:Joel Schopp<jschopp@austin.ibm.com>
^ space ^ space
Thanks !
Cheers,
Ben.
> The marker should be here or the line below:
>
> > Index: linux-2.6.git/arch/powerpc/kernel/prom_init.c
> > ===================================================================
>
> Would also end up in the comments.
>
> The rest looks fine.
>
> Cheers,
> Ben.
>
> > --- linux-2.6.git.orig/arch/powerpc/kernel/prom_init.c
> > +++ linux-2.6.git/arch/powerpc/kernel/prom_init.c
> > @@ -654,6 +656,9 @@ static void __init early_cmdline_parse(v
> > #define OV5_CMO 0x00
> > #endif
> >
> > +/* Option Vector 6: IBM PAPR hints */
> > +#define OV6_LINUX 0x02 /* Linux is our OS */
> > +
> > /*
> > * The architecture vector has an array of PVR mask/value pairs,
> > * followed by # option vectors - 1, followed by the option vectors.
> > @@ -665,7 +670,7 @@ static unsigned char ibm_architecture_ve
> > W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */
> > W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */
> > W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
> > - 5 - 1, /* 5 option vectors */
> > + 6 - 1, /* 6 option vectors */
> >
> > /* option vector 1: processor architectures supported */
> > 3 - 2, /* length */
> > @@ -697,12 +702,24 @@ static unsigned char ibm_architecture_ve
> > 0, /* don't halt */
> >
> > /* option vector 5: PAPR/OF options */
> > - 5 - 2, /* length */
> > + 13 - 2, /* length */
> > 0, /* don't ignore, don't halt */
> > OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
> > OV5_DONATE_DEDICATE_CPU | OV5_MSI,
> > 0,
> > OV5_CMO,
> > + 0,
> > + 0,
> > + 0,
> > + 0,
> > + W(NR_CPUS), /* number of cores supported*/
> > +
> > + /* option vector 6: IBM PAPR hints */
> > + 4 - 2, /* length */
> > + 0,
> > + 0,
> > + OV6_LINUX,
> > +
> > };
> >
> > /* Old method - ELF header with PT_NOTE sections */
> >
> >
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
>
^ permalink raw reply
* Re: [PATCH 2/2] Update ibm,client-architecture call field based on device tree
From: Benjamin Herrenschmidt @ 2010-01-15 2:58 UTC (permalink / raw)
To: Joel Schopp; +Cc: linuxppc-dev
In-Reply-To: <1263501674.4869.142.camel@jschopp-laptop>
On Thu, 2010-01-14 at 14:41 -0600, Joel Schopp wrote:
> In the previous patch the client-architecture field for the number of
> cores supported is set statically as high as is possible. However, that
> static setting could be too high if the system supports smt, resulting
> in cpus assigned to Linux that are not booted. This patch reads the
> device tree (before it is unflattened) to determine the amount of smt.
> It then dynamically updates the entires in the array with the proper
> number of cores supported. Tests show this correctly detecting SMT4 on
> a Power7 and still booting all the supported cores on a large machine.
Same comments about submission format as the previous patch...
> Signed-off-by:Joel Schopp<jschopp@austin.ibm.com>
> Index: linux-2.6.git/arch/powerpc/kernel/prom_init.c
> ===================================================================
> --- linux-2.6.git.orig/arch/powerpc/kernel/prom_init.c
> +++ linux-2.6.git/arch/powerpc/kernel/prom_init.c
> @@ -141,6 +141,8 @@ typedef u32 cell_t;
>
> extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
>
> +static int __init prom_smt_way(void);
Do you really need a forward declaration ? We generally avoid those and
prefer instead having the functions in the right order to make it
unnecessary.
> #ifdef CONFIG_PPC64
> extern int enter_prom(struct prom_args *args, unsigned long entry);
> #else
> @@ -811,9 +813,17 @@ static void __init prom_send_capabilitie
> {
> ihandle elfloader, root;
> prom_arg_t ret;
> + u32 *cores;
>
> root = call_prom("open", 1, 1, ADDR("/"));
> if (root != 0) {
> + /*
> + * If you add to the struct, please be sure the 100 index
> + * didn't change. The BUILD_BUG_ON is a reminder.
> + */
> + BUILD_BUG_ON(sizeof(ibm_architecture_vec) != 108);
This is indeed a bit fishy... a nicer way may have been to have the
vector in an asm file with labels but that's probably overkill. Just
maybe add a runtime test that checks the value read initially is
NR_CORES and if not, print a big fat warning ?
> + cores = (u32 *) &ibm_architecture_vec[100];
> + *cores = (u32) (NR_CPUS/prom_smt_way());
The style is a bit gross though I suppose it will do. Drop the cast on
the second line, it's not useful, and stick some spaces around that
division. Also maybe print out a message saying to what value you
adjusted the max number of supported cores, might be useful on the field
to diagnose issues.
> /* try calling the ibm,client-architecture-support method */
> prom_printf("Calling ibm,client-architecture-support...");
> if (call_prom_ret("call-method", 3, 2, &ret,
> @@ -1031,6 +1041,45 @@ static void __init reserve_mem(u64 base,
> RELOC(mem_reserve_cnt) = cnt + 1;
> }
>
> +
> +static int __init prom_smt_way(void)
> +{
> + phandle node;
> + char type[64];
> + unsigned int plen;
> +
> + for (node = 0; prom_next_node(&node); ) {
> + type[0] = 0;
> + prom_getprop(node, "device_type", type, sizeof(type));
> +
> + if (type[0] == 0) {
> + /*
> + * CHRP Longtrail machines have no device_type
> + * on the memory node, so check the name instead...
> + */
> + prom_getprop(node, "name", type, sizeof(type));
They also have no SMT :-) Just continue instead. You could also have
instead gone for /cpus and peeked at the first child. Might have lead to
a simpler construct (and faster runtime)
> + }
> + if (strcmp(type, RELOC("cpu")))
> + continue;
> +
> + /*
> + * There is an entry for each smt thread, each entry being
> + * 4 bytes long. All cpus should have the same number of
> + * smt threads, so return after finding the first.
> + */
> + plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
> + prom_debug("smt %x\n", (unsigned long) plen);
Might only be a debug message but it should be a tad more verbose about
what it's actually printing.
> + if (plen >= 4)
> + return plen / 4;
> + }
> + /*
> + * If things go wrong and we get here fallback to SMT1
> + */
> + prom_debug("unable to determine smt from device tree, guessing smt1\n");
> + return 1;
> +
> +}
> +
Cheers,
Ben.
> /*
> * Initialize memory allocation mechanism, parse "memory" nodes and
> * obtain that way the top of memory and RMO to setup out local allocator
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH -tip tracing/kprobes v2] Powerpc port of the kprobe-based event tracer
From: Benjamin Herrenschmidt @ 2010-01-15 3:12 UTC (permalink / raw)
To: Mahesh Salgaonkar
Cc: Michael Neuling, linux-kernel, linuxppc-dev, systemtap,
Ingo Molnar, Masami Hiramatsu
In-Reply-To: <20100111130210.GA31980@in.ibm.com>
Hi Mahesh !
> +/**
> + * regs_within_kernel_stack() - check the address in the stack
> + * @regs: pt_regs which contains kernel stack pointer.
> + * @addr: address which is checked.
> + *
> + * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
> + * If @addr is within the kernel stack, it returns true. If not, returns false.
> + */
> +
> +static inline bool regs_within_kernel_stack(struct pt_regs *regs,
> + unsigned long addr)
> +{
> + return ((addr & ~(THREAD_SIZE - 1)) ==
> + (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
> +}
Out of curiosity, what is the above meant for ? I'm trying to understand
because it will not work with such things as interrupt or softirq
stack...
> +/**
> + * regs_get_kernel_stack_nth() - get Nth entry of the stack
> + * @regs: pt_regs which contains kernel stack pointer.
> + * @n: stack entry number.
> + *
> + * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
> + * is specified by @regs. If the @n th entry is NOT in the kernel stack,
> + * this returns 0.
> + */
> +static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
> + unsigned int n)
> +{
> + unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
> + addr += n;
> + if (regs_within_kernel_stack(regs, (unsigned long)addr))
> + return *addr;
> + else
> + return 0;
> +}
Is this meant to fetch stack based arguments or do backtraces or similar
or does this have a different purpose ?
> /*
> * These are defined as per linux/ptrace.h, which see.
> */
> diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
> index ef14988..e816aba 100644
> --- a/arch/powerpc/kernel/ptrace.c
> +++ b/arch/powerpc/kernel/ptrace.c
> @@ -39,6 +39,108 @@
> #include <asm/system.h>
>
> /*
> + * The parameter save area on the stack is used to store arguments being passed
> + * to callee function and is located at fixed offset from stack pointer.
> + */
> +#ifdef CONFIG_PPC32
> +#define PARAMETER_SAVE_AREA_OFFSET 24 /* bytes */
> +#else /* CONFIG_PPC32 */
> +#define PARAMETER_SAVE_AREA_OFFSET 48 /* bytes */
> +#endif
> +
> +struct pt_regs_offset {
> + const char *name;
> + int offset;
> +};
> +
> +#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
> +#define REG_OFFSET_END {.name = NULL, .offset = 0}
> +
> +static const struct pt_regs_offset regoffset_table[] = {
> + REG_OFFSET_NAME(gpr[0]),
> + REG_OFFSET_NAME(gpr[1]),
> + REG_OFFSET_NAME(gpr[2]),
> + REG_OFFSET_NAME(gpr[3]),
> + REG_OFFSET_NAME(gpr[4]),
> + REG_OFFSET_NAME(gpr[5]),
> + REG_OFFSET_NAME(gpr[6]),
> + REG_OFFSET_NAME(gpr[7]),
> + REG_OFFSET_NAME(gpr[8]),
> + REG_OFFSET_NAME(gpr[9]),
> + REG_OFFSET_NAME(gpr[10]),
> + REG_OFFSET_NAME(gpr[11]),
> + REG_OFFSET_NAME(gpr[12]),
> + REG_OFFSET_NAME(gpr[13]),
> + REG_OFFSET_NAME(gpr[14]),
> + REG_OFFSET_NAME(gpr[15]),
> + REG_OFFSET_NAME(gpr[16]),
> + REG_OFFSET_NAME(gpr[17]),
> + REG_OFFSET_NAME(gpr[18]),
> + REG_OFFSET_NAME(gpr[19]),
> + REG_OFFSET_NAME(gpr[20]),
> + REG_OFFSET_NAME(gpr[21]),
> + REG_OFFSET_NAME(gpr[22]),
> + REG_OFFSET_NAME(gpr[23]),
> + REG_OFFSET_NAME(gpr[24]),
> + REG_OFFSET_NAME(gpr[25]),
> + REG_OFFSET_NAME(gpr[26]),
> + REG_OFFSET_NAME(gpr[27]),
> + REG_OFFSET_NAME(gpr[28]),
> + REG_OFFSET_NAME(gpr[29]),
> + REG_OFFSET_NAME(gpr[30]),
> + REG_OFFSET_NAME(gpr[31]),
I find it weird that you have the [ an ] in the name ... We usually name
these guys gpr0...gpr31 or even r0...r31. Is that name user visible ?
Maybe you should use a different macro GPR_OFFSET_NAME(num) that
generates both gpr[num] for the offsetof and r##num for the register
name.
> + REG_OFFSET_NAME(nip),
> + REG_OFFSET_NAME(msr),
> + REG_OFFSET_NAME(orig_gpr3),
> + REG_OFFSET_NAME(ctr),
> + REG_OFFSET_NAME(link),
> + REG_OFFSET_NAME(xer),
> + REG_OFFSET_NAME(ccr),
> +#ifdef CONFIG_PPC64
> + REG_OFFSET_NAME(softe),
> +#else
> + REG_OFFSET_NAME(mq),
> +#endif
> + REG_OFFSET_NAME(trap),
> + REG_OFFSET_NAME(dar),
> + REG_OFFSET_NAME(dsisr),
> + REG_OFFSET_NAME(result),
> + REG_OFFSET_END,
> +};
Do you need to expose orig_gpr3 and result there ?
Cheers,
Ben.
^ permalink raw reply
* Re: xilinx-pci driver and pci in general
From: Michal Simek @ 2010-01-15 9:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Arnd Bergmann, linuxppc-dev, thunderbird2k, LKML, michal.simek,
John Williams
In-Reply-To: <1263434836.724.317.camel@pasglop>
Benjamin Herrenschmidt wrote:
> On Wed, 2010-01-13 at 16:23 +0100, Michal Simek wrote:
>
>> The main problems are:
>> ppc use ppc_md struct which we don't have it on Microblaze.
>> xilinx-pci driver uses exclude_device function. This function is used in
>> indirect_pci.c too. There could be a way to move that function directly
>> to pci_controller structure which could be useful for other controllers
>> too. What do you think?
>>
>> Then there are some other ppc_md. calling like pcibios_after_init which
>> if I see correctly not used for ppc too.
>
> We may not be using after_init() anymore in which case you are welcome
> to send a patch to remove it :-)
hmm. I used older kernel and I see that in the latest version powermac
use it. :-( I will just remove it.
>
> As for the others, well ... maybe you can do wrappers for these that
> call into ppc_md. on powerpc and into some kind of arch_pci_ops. that
> the platform provides on microblaze ?
>
> I'm not sure moving them into the pci_controller is the best way to go
> there.
ok. I will remove that part of code for now.
>
>> The next thing is that some files contains asm/machdep.h which could be
>> added to asm/pci-bridge.h and the same is for asm/ppc-pci.h
>
> Yeah, moving includes like that is ok.
>
>> Files contains CONFIG_PPC_OF and we would like to use only CONFIG_OF.
>> I remember any discuss around but not sure what was the conclusion on
>> powerpc.
>
> I think that should be allright, Grant, any objection there ?
>
>> Part of headers are the same that's why there will be a space to move
>> them to asm-generic.
>
> If you can convince other archs that it makes sense to do so ? :-)
will try.
>
>> Anyway: I look at your dma-mapping.h and you can use
>> asm-generic/dma-mapping-common.h as I am using.
>
> Not just quite yet, there's still some stuff we need to cleanup with
> the !coherent cases.
>
>> Then I have some question about EARLY_PCI_OP in ppc_32.c. Is there any
>> reason to use early_##rw##_config_##size fucntions instead of proper
>> pci_bus_##rw##_config_##size functions?
>> There is one comment that these functions are used before PCI scanning
>> is done but there are used the same function as are in driver/pci/access.c.
>> Is there any "secret" reason to do it in this way?
>
> Well, first of all, those aren't ppc32 only anymore, they are in
> pci-common.c now. Then, if you look at them you'll notice that
> they are just a wrapper on top of pci_bus_* which uses a fake
> pci_bus structure. IE. They are meant to be used in very early
> arch fixup code at a time when we may not even have the struct
> pci_bus at hand. Their use is pretty rare though, maybe we -could-
> get rid of them at some stage by moving some of that fixup code.
Thanks for that.
>
>> Thanks for this early discuss. I would like to hear your opinion and
>> then I will choose solution how to add our pci support to mainline.
I will keep you informed but I see that I will add that part of code to
mainline and then we look at consolidation work.
Thanks,
Michal
>
> Cheers,
> Ben.
>
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
--
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
^ permalink raw reply
* Re: Problem dtb file booting Kernel 2.6.32
From: Andres F Marquez @ 2010-01-15 14:30 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <4B4F9059.9050705@freescale.com>
[-- Attachment #1: Type: text/plain, Size: 2764 bytes --]
Hello,
I was able to boot Kernel 2.6.26.8 (using our old dts file from
Kernel 2.6.25). However, I need to upgrade to a newer Kernel because
I am having serious problems with the ethernet interface under heavy
load. I am not sure if it could be a scheduling problem or the network
driver. CPU usage is low but load average is high (more than 4).
The main difference that I could find is that for newer Kernels the
/arch/ppc was removed. I also read online that dts version changed
from 0 to 1 somewhere around Kernel 2.6.27 or so.
Following your instruction, I executed in the LTIB command shell:
LTIB> dtc -I dtb -O dts ../mpc8272ads.dtb
I executed that command passing as argument the old working dtb file.
I got a dts file which I placed in the new Kernel and compiled.
Unfortunately, I am still getting the same error.
Attached you can find both dts files.
Thank you.
--
Andres F Marquez
EdgeAccess
Development
amarquez@edgeaccess.net
On Thu, 2010-01-14 at 15:44 -0600, Scott Wood wrote:
> Andres F Marquez wrote:
> > Hello,
> >
> > I am working on a MPC8265 board which I have successfully ported Linux
> > Kernel 2.6.25 to. I am trying to upgrade the Kernel but have not got
> > good results (I am able to compile the Kernel for my powerpc, but not to
> > boot it). The problem appears to be something related to the interaction
> > between the dtb and the Kernel. I am not sure if the syntax for the dts
> > file may have changed from Kernel 2.6.25 to newer versions (I have tried
> > 2.6.27.43 - 2.6.32.2 and 2.6.31.11 getting very similar results).
>
> Can you bisect between 2.6.25 and 2.6.27 to see which commit may have
> broken it?
>
> What sort of changes did you make to get 2.6.25 to work?
>
> > When I build the dtb file from the /arch/powerpc/boot/dts/MPC8272ADS.dts
> > file that comes with the new Kernel, the booting process gets stuck
> > after trying to load the device tree:
> >
> > ## Booting image at ff810000 ...
> > Image Name: Linux-2.6.27.43
> > Image Type: PowerPC Linux Kernel Image (gzip
> > compressed)
> > Data Size: 1365263 Bytes = 1.3 MB
> > Load Address: 00000000
> > Entry Point: 00000000
> > Verifying Checksum ... OK
> > Uncompressing Kernel Image ... OK
> > Booting using the fdt at 0xff802000
> > Loading Device Tree to 007fc000, end 007fefff ... OK
> >
> >
> > However, when I boot the new Kernel with the old compiled dtb file
> > (the one that works with the Kernel 2.6.25) the process moves forward
> > but stops at a time when displaying information about IRQ 40 line
> > (related to the Programmable Interrup Controller (PIC)):
>
> Decompile that device tree blob using dtc -I dtb -O dts, and look for
> differences.
>
> -Scott
[-- Attachment #2: mpc8272ads-Kernel-2.6.25.dts --]
[-- Type: text/plain, Size: 5757 bytes --]
/*
* Device Tree for the PQ2FADS-ZU board with an MPC8280 chip.
*
* Copyright 2007 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/ {
model = "pq2fads";
compatible = "fsl,pq2fads";
#address-cells = <1>;
#size-cells = <1>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
reg = <0>;
d-cache-line-size = <d#32>;
i-cache-line-size = <d#32>;
d-cache-size = <d#16384>;
i-cache-size = <d#16384>;
timebase-frequency = <0>;
clock-frequency = <0>;
};
};
memory {
device_type = "memory";
reg = <00000000 02000000>;
};
localbus@f0010100 {
compatible = "fsl,mpc8280-localbus",
"fsl,pq2-localbus";
#address-cells = <2>;
#size-cells = <1>;
reg = <f0010100 60>;
ranges = <0 0 fe000000 00800000
1 0 f4500000 00008000
8 0 f8200000 00008000>;
flash@0,0 {
compatible = "jedec-flash";
reg = <0 0 800000>;
bank-width = <4>;
device-width = <1>;
};
bcsr@1,0 {
reg = <1 0 20>;
compatible = "fsl,pq2fads-bcsr";
};
PCI_PIC: pic@8,0 {
#interrupt-cells = <1>;
interrupt-controller;
reg = <8 0 8>;
compatible = "fsl,pq2ads-pci-pic";
interrupt-parent = <&PIC>;
interrupts = <18 8>;
};
};
pci@f0010800 {
device_type = "pci";
reg = <f0010800 10c f00101ac 8 f00101c4 8>;
compatible = "fsl,mpc8280-pci", "fsl,pq2-pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
clock-frequency = <d#66000000>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x16 */
b000 0 0 1 &PCI_PIC 0
b000 0 0 2 &PCI_PIC 1
b000 0 0 3 &PCI_PIC 2
b000 0 0 4 &PCI_PIC 3
/* IDSEL 0x17 */
b800 0 0 1 &PCI_PIC 4
b800 0 0 2 &PCI_PIC 5
b800 0 0 3 &PCI_PIC 6
b800 0 0 4 &PCI_PIC 7
/* IDSEL 0x18 */
c000 0 0 1 &PCI_PIC 8
c000 0 0 2 &PCI_PIC 9
c000 0 0 3 &PCI_PIC a
c000 0 0 4 &PCI_PIC b>;
interrupt-parent = <&PIC>;
interrupts = <12 8>;
ranges = <42000000 0 80000000 80000000 0 20000000
02000000 0 a0000000 a0000000 0 20000000
01000000 0 00000000 f6000000 0 02000000>;
};
soc@f0000000 {
#address-cells = <1>;
#size-cells = <1>;
device_type = "soc";
compatible = "fsl,mpc8280", "fsl,pq2-soc";
ranges = <00000000 f0000000 00053000>;
// Temporary -- will go away once kernel uses ranges for get_immrbase().
reg = <f0000000 00053000>;
cpm@119c0 {
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
compatible = "fsl,mpc8280-cpm", "fsl,cpm2";
reg = <119c0 30>;
ranges;
muram@0 {
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0 10000>;
data@0 {
compatible = "fsl,cpm-muram-data";
reg = <0 2000 9800 800>;
};
};
brg@119f0 {
compatible = "fsl,mpc8280-brg",
"fsl,cpm2-brg",
"fsl,cpm-brg";
reg = <119f0 10 115f0 10>;
};
serial@11a00 {
device_type = "serial";
compatible = "fsl,mpc8280-scc-uart",
"fsl,cpm2-scc-uart";
reg = <11a00 20 8000 100>;
interrupts = <28 8>;
interrupt-parent = <&PIC>;
fsl,cpm-brg = <1>;
fsl,cpm-command = <00800000>;
};
serial@11a20 {
device_type = "serial";
compatible = "fsl,mpc8280-scc-uart",
"fsl,cpm2-scc-uart";
reg = <11a20 20 8100 100>;
interrupts = <29 8>;
interrupt-parent = <&PIC>;
fsl,cpm-brg = <2>;
fsl,cpm-command = <04a00000>;
};
ethernet@11320 {
device_type = "network";
compatible = "fsl,mpc8280-fcc-enet",
"fsl,cpm2-fcc-enet";
reg = <11320 20 8500 100 113b0 1>;
interrupts = <21 8>;
interrupt-parent = <&PIC>;
phy-handle = <&PHY0>;
linux,network-index = <0>;
fsl,cpm-command = <16200300>;
local-mac-address = [00 e0 0a 0b 79 01];
};
ethernet@11340 {
device_type = "network";
compatible = "fsl,mpc8280-fcc-enet",
"fsl,cpm2-fcc-enet";
reg = <11340 20 8600 100 113d0 1>;
interrupts = <22 8>;
interrupt-parent = <&PIC>;
phy-handle = <&PHY1>;
linux,network-index = <1>;
fsl,cpm-command = <1a400300>;
local-mac-address = [00 e0 0c 00 79 01];
};
mdio@10d40 {
device_type = "mdio";
compatible = "fsl,pq2fads-mdio-bitbang",
"fsl,mpc8280-mdio-bitbang",
"fsl,cpm2-mdio-bitbang";
#address-cells = <1>;
#size-cells = <0>;
reg = <10d40 14>;
fsl,mdio-pin = <9>;
fsl,mdc-pin = <a>;
PHY0: ethernet-phy@0 {
interrupt-parent = <&PIC>;
interrupts = <19 2>;
reg = <0>;
device_type = "ethernet-phy";
};
PHY1: ethernet-phy@1 {
interrupt-parent = <&PIC>;
interrupts = <19 2>;
reg = <3>;
device_type = "ethernet-phy";
};
};
usb@11b60 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,mpc8280-usb",
"fsl,cpm2-usb";
reg = <11b60 18 8b00 100>;
interrupt-parent = <&PIC>;
interrupts = <b 8>;
fsl,cpm-command = <2e600000>;
};
};
PIC: interrupt-controller@10c00 {
#interrupt-cells = <2>;
interrupt-controller;
reg = <10c00 80>;
compatible = "fsl,mpc8280-pic", "fsl,cpm2-pic";
};
};
chosen {
linux,stdout-path = "/soc/cpm/serial@11a00";
};
};
[-- Attachment #3: mpc8272ads-Kernel-2.6.32.2.dts --]
[-- Type: text/plain, Size: 3724 bytes --]
/*
* Device Tree for the PQ2FADS-ZU board with an MPC8280 chip.
*
* Copyright 2007 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/ {
model = "pq2fads";
compatible = "fsl,pq2fads";
#address-cells = <1>;
#size-cells = <1>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
reg = <0>;
d-cache-line-size = <32>;
i-cache-line-size = <32>;
d-cache-size = <16384>;
i-cache-size = <16384>;
timebase-frequency = <0>;
clock-frequency = <0>;
};
};
memory {
device_type = "memory";
reg = <00000000 02000000>;
};
soc@f0000000 {
#address-cells = <1>;
#size-cells = <1>;
device_type = "soc";
compatible = "fsl,mpc8280", "fsl,pq2-soc";
ranges = <00000000 f0000000 00053000>;
// Temporary -- will go away once kernel uses ranges for get_immrbase().
reg = <f0000000 00053000>;
cpm@119c0 {
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
compatible = "fsl,mpc8280-cpm", "fsl,cpm2";
reg = <119c0 30>;
ranges;
muram@0 {
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0 10000>;
data@0 {
compatible = "fsl,cpm-muram-data";
reg = <0 2000 9800 800>;
};
};
brg@119f0 {
compatible = "fsl,mpc8280-brg",
"fsl,cpm2-brg",
"fsl,cpm-brg";
reg = <119f0 10 115f0 10>;
};
serial@11a00 {
device_type = "serial";
compatible = "fsl,mpc8280-scc-uart",
"fsl,cpm2-scc-uart";
reg = <11a00 20 8000 100>;
interrupts = <40 8>;
interrupt-parent = <&PIC>;
fsl,cpm-brg = <1>;
fsl,cpm-command = <00800000>;
};
serial@11a20 {
device_type = "serial";
compatible = "fsl,mpc8280-scc-uart",
"fsl,cpm2-scc-uart";
reg = <11a20 20 8100 100>;
interrupts = <41 8>;
interrupt-parent = <&PIC>;
fsl,cpm-brg = <2>;
fsl,cpm-command = <04a00000>;
};
ethernet@11320 {
device_type = "network";
compatible = "fsl,mpc8280-fcc-enet",
"fsl,cpm2-fcc-enet";
reg = <11320 20 8500 100 113b0 1>;
interrupts = <33 8>;
interrupt-parent = <&PIC>;
phy-handle = <&PHY0>;
linux,network-index = <0>;
fsl,cpm-command = <16200300>;
local-mac-address = [00 e0 0a 0b 79 01];
};
ethernet@11340 {
device_type = "network";
compatible = "fsl,mpc8280-fcc-enet",
"fsl,cpm2-fcc-enet";
reg = <11340 20 8600 100 113d0 1>;
interrupts = <34 8>;
interrupt-parent = <&PIC>;
phy-handle = <&PHY1>;
linux,network-index = <1>;
fsl,cpm-command = <1a400300>;
local-mac-address = [00 e0 0c 00 79 01];
};
mdio@10d40 {
device_type = "mdio";
compatible = "fsl,pq2fads-mdio-bitbang",
"fsl,mpc8280-mdio-bitbang",
"fsl,cpm2-mdio-bitbang";
#address-cells = <1>;
#size-cells = <0>;
reg = <10d40 14>;
fsl,mdio-pin = <9>;
fsl,mdc-pin = <a>;
PHY0: ethernet-phy@0 {
interrupt-parent = <&PIC>;
interrupts = <25 2>;
reg = <0>;
device_type = "ethernet-phy";
};
PHY1: ethernet-phy@1 {
interrupt-parent = <&PIC>;
interrupts = <25 2>;
reg = <3>;
device_type = "ethernet-phy";
};
};
};
PIC: interrupt-controller@10c00 {
#interrupt-cells = <2>;
interrupt-controller;
reg = <10c00 80>;
compatible = "fsl,mpc8280-pic", "fsl,cpm2-pic";
};
};
chosen {
linux,stdout-path = "/soc/cpm/serial@11a00";
};
};
^ permalink raw reply
* [PATCH 5/5] powerpc/kexec: Add support for FSL-BookE
From: Sebastian Andrzej Siewior @ 2010-01-15 16:41 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Sebastian Andrzej Siewior
In-Reply-To: <1263573697-17839-1-git-send-email-linuxppc-dev@ml.breakpoint.cc>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
This adds support kexec on FSL-BookE where the MMU can not be simply
switched off. The code borrows the initial MMU-setup code to create the
identical mapping mapping. The only difference to the original boot code
is the size of the mapping(s) and the executeable address.
The kexec code maps the first 2 GiB of memory in 256 MiB steps. This
should work also on e500v1 boxes.
SMP support is still not available.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/kexec.h | 13 +++++++++
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 34 +++++++++++++++++++++++++
arch/powerpc/kernel/head_fsl_booke.S | 2 +
arch/powerpc/kernel/misc_32.S | 17 ++++++++++++
5 files changed, 67 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ba3948c..788a154 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -335,7 +335,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
- depends on PPC_BOOK3S && EXPERIMENTAL
+ depends on (PPC_BOOK3S || (FSL_BOOKE && !SMP)) && EXPERIMENTAL
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index 7e06b43..83f6481 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -2,6 +2,18 @@
#define _ASM_POWERPC_KEXEC_H
#ifdef __KERNEL__
+#ifdef CONFIG_FSL_BOOKE
+
+/*
+ * On FSL-BookE we setup a 1:1 mapping which covers the first 2GiB of memory
+ * and therefore we can only deal with memory within this range
+ */
+#define KEXEC_SOURCE_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
+#define KEXEC_DESTINATION_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
+#define KEXEC_CONTROL_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
+
+#else
+
/*
* Maximum page that is mapped directly into kernel memory.
* XXX: Since we copy virt we can use any page we allocate
@@ -21,6 +33,7 @@
/* TASK_SIZE, probably left over from use_mm ?? */
#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
#endif
+#endif
#define KEXEC_CONTROL_PAGE_SIZE 4096
diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
index d629618..1fc283a 100644
--- a/arch/powerpc/kernel/fsl_booke_entry_mapping.S
+++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
@@ -155,6 +155,8 @@ skpinv: addi r6,r6,1 /* Increment */
#define M_IF_SMP 0
#endif
+#if defined(ENTRY_MAPPING_BOOT_SETUP)
+
/* 6. Setup KERNELBASE mapping in TLB1[0] */
lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
mtspr SPRN_MAS0,r6
@@ -170,6 +172,38 @@ skpinv: addi r6,r6,1 /* Increment */
/* 7. Jump to KERNELBASE mapping */
lis r6,(KERNELBASE & ~0xfff)@h
ori r6,r6,(KERNELBASE & ~0xfff)@l
+
+#elif defined(ENTRY_MAPPING_KEXEC_SETUP)
+/*
+ * 6. Setup 1:1 mapping TLB1[0 - 8]. We start 0 and map in 256 MiB steps the
+ * first 2GiB of memory.
+ */
+ lis r10, (MAS1_VALID|MAS1_IPROT)@h
+ ori r10,r10, (MAS1_TSIZE(BOOK3E_PAGESZ_256M))@l
+ li r11, 0 // We use 16 esel slots and map 4 GiB
+ li r0, 8 // of mem 1:1 from 0 to 4 GiB - 1 in
+ mtctr r0 // 256 MiB mem steps
+
+next_tlb_setup:
+ rlwinm r0, r11, 16, 4, 15 // Compute esel
+ rlwinm r9, r11, 28, 0, 3 // Compute [ER]PN
+ oris r0, r0, (MAS0_TLBSEL(1))@h
+ mtspr SPRN_MAS0,r0
+ mtspr SPRN_MAS1,r10
+ mtspr SPRN_MAS2,r9
+ ori r9, r9, (MAS3_SX|MAS3_SW|MAS3_SR)
+ mtspr SPRN_MAS3,r9
+ tlbwe
+ addi r11, r11, 1
+ bdnz+ next_tlb_setup
+
+/* 7. Jump to KERNELBASE mapping */
+ li r6, 0
+
+#else
+ #error You need to specify the mapping or not use this at all.
+#endif
+
lis r7,MSR_KERNEL@h
ori r7,r7,MSR_KERNEL@l
bl 1f /* Find our address */
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 4de9bc5..fcace7b 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -95,7 +95,9 @@ _ENTRY(_start);
_ENTRY(__early_start)
+#define ENTRY_MAPPING_BOOT_SETUP
#include "fsl_booke_entry_mapping.S"
+#undef ENTRY_MAPPING_BOOT_SETUP
/* Establish the interrupt vector offsets */
SET_IVOR(0, CriticalInput);
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 8649f53..99bc652 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -706,6 +706,22 @@ relocate_new_kernel:
/* r4 = reboot_code_buffer */
/* r5 = start_address */
+#ifdef CONFIG_FSL_BOOKE
+
+ mr r29, r3
+ mr r30, r4
+ mr r31, r5
+
+#define ENTRY_MAPPING_KEXEC_SETUP
+#include "fsl_booke_entry_mapping.S"
+#undef ENTRY_MAPPING_KEXEC_SETUP
+
+ mr r3, r29
+ mr r4, r30
+ mr r5, r31
+
+ li r0, 0
+#else
li r0, 0
/*
@@ -722,6 +738,7 @@ relocate_new_kernel:
rfi
1:
+#endif
/* from this point address translation is turned off */
/* and interrupts are disabled */
--
1.6.2.5
^ permalink raw reply related
* [PATCH 4/5] powerpc/fsl head: move the entry setup code into a seperate file
From: Sebastian Andrzej Siewior @ 2010-01-15 16:41 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Sebastian Andrzej Siewior
In-Reply-To: <1263573697-17839-1-git-send-email-linuxppc-dev@ml.breakpoint.cc>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
This patch moves only the initial entry code which setups the mapping
from what ever to KERNELBASE into a seperate file. No code change has
been made here.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
arch/powerpc/kernel/fsl_booke_entry_mapping.S | 189 +++++++++++++++++++++++++
arch/powerpc/kernel/head_fsl_booke.S | 189 +------------------------
2 files changed, 190 insertions(+), 188 deletions(-)
create mode 100644 arch/powerpc/kernel/fsl_booke_entry_mapping.S
diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
new file mode 100644
index 0000000..d629618
--- /dev/null
+++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S
@@ -0,0 +1,189 @@
+/* 1. Find the index of the entry we're executing in */
+ bl invstr /* Find our address */
+invstr: mflr r6 /* Make it accessible */
+ mfmsr r7
+ rlwinm r4,r7,27,31,31 /* extract MSR[IS] */
+ mfspr r7, SPRN_PID0
+ slwi r7,r7,16
+ or r7,r7,r4
+ mtspr SPRN_MAS6,r7
+ tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */
+ mfspr r7,SPRN_MAS1
+ andis. r7,r7,MAS1_VALID@h
+ bne match_TLB
+
+ mfspr r7,SPRN_MMUCFG
+ rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
+ cmpwi r7,3
+ bne match_TLB /* skip if NPIDS != 3 */
+
+ mfspr r7,SPRN_PID1
+ slwi r7,r7,16
+ or r7,r7,r4
+ mtspr SPRN_MAS6,r7
+ tlbsx 0,r6 /* search MSR[IS], SPID=PID1 */
+ mfspr r7,SPRN_MAS1
+ andis. r7,r7,MAS1_VALID@h
+ bne match_TLB
+ mfspr r7, SPRN_PID2
+ slwi r7,r7,16
+ or r7,r7,r4
+ mtspr SPRN_MAS6,r7
+ tlbsx 0,r6 /* Fall through, we had to match */
+
+match_TLB:
+ mfspr r7,SPRN_MAS0
+ rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */
+
+ mfspr r7,SPRN_MAS1 /* Insure IPROT set */
+ oris r7,r7,MAS1_IPROT@h
+ mtspr SPRN_MAS1,r7
+ tlbwe
+
+/* 2. Invalidate all entries except the entry we're executing in */
+ mfspr r9,SPRN_TLB1CFG
+ andi. r9,r9,0xfff
+ li r6,0 /* Set Entry counter to 0 */
+1: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
+ rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */
+ mtspr SPRN_MAS0,r7
+ tlbre
+ mfspr r7,SPRN_MAS1
+ rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */
+ cmpw r3,r6
+ beq skpinv /* Dont update the current execution TLB */
+ mtspr SPRN_MAS1,r7
+ tlbwe
+ isync
+skpinv: addi r6,r6,1 /* Increment */
+ cmpw r6,r9 /* Are we done? */
+ bne 1b /* If not, repeat */
+
+ /* Invalidate TLB0 */
+ li r6,0x04
+ tlbivax 0,r6
+ TLBSYNC
+ /* Invalidate TLB1 */
+ li r6,0x0c
+ tlbivax 0,r6
+ TLBSYNC
+
+/* 3. Setup a temp mapping and jump to it */
+ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
+ rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
+ mtspr SPRN_MAS0,r7
+ tlbre
+
+ /* grab and fixup the RPN */
+ mfspr r6,SPRN_MAS1 /* extract MAS1[SIZE] */
+ rlwinm r6,r6,25,27,31
+ li r8,-1
+ addi r6,r6,10
+ slw r6,r8,r6 /* convert to mask */
+
+ bl 1f /* Find our address */
+1: mflr r7
+
+ mfspr r8,SPRN_MAS3
+#ifdef CONFIG_PHYS_64BIT
+ mfspr r23,SPRN_MAS7
+#endif
+ and r8,r6,r8
+ subfic r9,r6,-4096
+ and r9,r9,r7
+
+ or r25,r8,r9
+ ori r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
+
+ /* Just modify the entry ID and EPN for the temp mapping */
+ li r7, 0 /* Set MAS0(TLBSEL) = 0 | ESEL(0) */
+ mtspr SPRN_MAS0,r7
+ xori r6,r4,1 /* Setup TMP mapping in the other Address space */
+ slwi r6,r6,12
+ oris r6,r6,(MAS1_VALID)@h
+ ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
+ mtspr SPRN_MAS1,r6
+ mfspr r6,SPRN_MAS2
+ li r7,0 /* temp EPN = 0 */
+ rlwimi r7,r6,0,20,31
+ mtspr SPRN_MAS2,r7
+ mtspr SPRN_MAS3,r8
+ tlbwe
+
+ xori r6,r4,1
+ slwi r6,r6,5 /* setup new context with other address space */
+ bl 1f /* Find our address */
+1: mflr r9
+ rlwimi r7,r9,0,20,31
+ addi r7,r7,(2f - 1b)
+ mtspr SPRN_SRR0,r7
+ mtspr SPRN_SRR1,r6
+ rfi
+2:
+/* 4. Clear out PIDs & Search info */
+ li r6,0
+ mtspr SPRN_MAS6,r6
+ mtspr SPRN_PID0,r6
+
+ mfspr r7,SPRN_MMUCFG
+ rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
+ cmpwi r7,3
+ bne 2f /* skip if NPIDS != 3 */
+
+ mtspr SPRN_PID1,r6
+ mtspr SPRN_PID2,r6
+
+/* 5. Invalidate mapping we started in */
+2:
+ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
+ rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
+ mtspr SPRN_MAS0,r7
+ tlbre
+ mfspr r6,SPRN_MAS1
+ rlwinm r6,r6,0,2,0 /* clear IPROT */
+ mtspr SPRN_MAS1,r6
+ tlbwe
+ /* Invalidate TLB1 */
+ li r9,0x0c
+ tlbivax 0,r9
+ TLBSYNC
+
+/* The mapping only needs to be cache-coherent on SMP */
+#ifdef CONFIG_SMP
+#define M_IF_SMP MAS2_M
+#else
+#define M_IF_SMP 0
+#endif
+
+/* 6. Setup KERNELBASE mapping in TLB1[0] */
+ lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
+ mtspr SPRN_MAS0,r6
+ lis r6,(MAS1_VALID|MAS1_IPROT)@h
+ ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
+ mtspr SPRN_MAS1,r6
+ lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
+ ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
+ mtspr SPRN_MAS2,r6
+ mtspr SPRN_MAS3,r8
+ tlbwe
+
+/* 7. Jump to KERNELBASE mapping */
+ lis r6,(KERNELBASE & ~0xfff)@h
+ ori r6,r6,(KERNELBASE & ~0xfff)@l
+ lis r7,MSR_KERNEL@h
+ ori r7,r7,MSR_KERNEL@l
+ bl 1f /* Find our address */
+1: mflr r9
+ rlwimi r6,r9,0,20,31
+ addi r6,r6,(2f - 1b)
+ add r6, r6, r25
+ mtspr SPRN_SRR0,r6
+ mtspr SPRN_SRR1,r7
+ rfi /* start execution out of TLB1[0] entry */
+
+/* 8. Clear out the temp mapping */
+2:
+ /* Invalidate TLB0 */
+ li r9,0x04
+ tlbivax 0,r9
+ TLBSYNC
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 445eddd..4de9bc5 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -94,195 +94,8 @@ _ENTRY(_start);
*/
_ENTRY(__early_start)
-/* 1. Find the index of the entry we're executing in */
- bl invstr /* Find our address */
-invstr: mflr r6 /* Make it accessible */
- mfmsr r7
- rlwinm r4,r7,27,31,31 /* extract MSR[IS] */
- mfspr r7, SPRN_PID0
- slwi r7,r7,16
- or r7,r7,r4
- mtspr SPRN_MAS6,r7
- tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */
- mfspr r7,SPRN_MAS1
- andis. r7,r7,MAS1_VALID@h
- bne match_TLB
-
- mfspr r7,SPRN_MMUCFG
- rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
- cmpwi r7,3
- bne match_TLB /* skip if NPIDS != 3 */
-
- mfspr r7,SPRN_PID1
- slwi r7,r7,16
- or r7,r7,r4
- mtspr SPRN_MAS6,r7
- tlbsx 0,r6 /* search MSR[IS], SPID=PID1 */
- mfspr r7,SPRN_MAS1
- andis. r7,r7,MAS1_VALID@h
- bne match_TLB
- mfspr r7, SPRN_PID2
- slwi r7,r7,16
- or r7,r7,r4
- mtspr SPRN_MAS6,r7
- tlbsx 0,r6 /* Fall through, we had to match */
-
-match_TLB:
- mfspr r7,SPRN_MAS0
- rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */
-
- mfspr r7,SPRN_MAS1 /* Insure IPROT set */
- oris r7,r7,MAS1_IPROT@h
- mtspr SPRN_MAS1,r7
- tlbwe
-
-/* 2. Invalidate all entries except the entry we're executing in */
- mfspr r9,SPRN_TLB1CFG
- andi. r9,r9,0xfff
- li r6,0 /* Set Entry counter to 0 */
-1: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
- rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */
- mtspr SPRN_MAS0,r7
- tlbre
- mfspr r7,SPRN_MAS1
- rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */
- cmpw r3,r6
- beq skpinv /* Dont update the current execution TLB */
- mtspr SPRN_MAS1,r7
- tlbwe
- isync
-skpinv: addi r6,r6,1 /* Increment */
- cmpw r6,r9 /* Are we done? */
- bne 1b /* If not, repeat */
-
- /* Invalidate TLB0 */
- li r6,0x04
- tlbivax 0,r6
- TLBSYNC
- /* Invalidate TLB1 */
- li r6,0x0c
- tlbivax 0,r6
- TLBSYNC
-
-/* 3. Setup a temp mapping and jump to it */
- lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
- rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
- mtspr SPRN_MAS0,r7
- tlbre
-
- /* grab and fixup the RPN */
- mfspr r6,SPRN_MAS1 /* extract MAS1[SIZE] */
- rlwinm r6,r6,25,27,31
- li r8,-1
- addi r6,r6,10
- slw r6,r8,r6 /* convert to mask */
-
- bl 1f /* Find our address */
-1: mflr r7
-
- mfspr r8,SPRN_MAS3
-#ifdef CONFIG_PHYS_64BIT
- mfspr r23,SPRN_MAS7
-#endif
- and r8,r6,r8
- subfic r9,r6,-4096
- and r9,r9,r7
-
- or r25,r8,r9
- ori r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
-
- /* Just modify the entry ID and EPN for the temp mapping */
- li r7, 0 /* Set MAS0(TLBSEL) = 0 | ESEL(0) */
- mtspr SPRN_MAS0,r7
- xori r6,r4,1 /* Setup TMP mapping in the other Address space */
- slwi r6,r6,12
- oris r6,r6,(MAS1_VALID)@h
- ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
- mtspr SPRN_MAS1,r6
- mfspr r6,SPRN_MAS2
- li r7,0 /* temp EPN = 0 */
- rlwimi r7,r6,0,20,31
- mtspr SPRN_MAS2,r7
- mtspr SPRN_MAS3,r8
- tlbwe
-
- xori r6,r4,1
- slwi r6,r6,5 /* setup new context with other address space */
- bl 1f /* Find our address */
-1: mflr r9
- rlwimi r7,r9,0,20,31
- addi r7,r7,(2f - 1b)
- mtspr SPRN_SRR0,r7
- mtspr SPRN_SRR1,r6
- rfi
-2:
-/* 4. Clear out PIDs & Search info */
- li r6,0
- mtspr SPRN_MAS6,r6
- mtspr SPRN_PID0,r6
-
- mfspr r7,SPRN_MMUCFG
- rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
- cmpwi r7,3
- bne 2f /* skip if NPIDS != 3 */
- mtspr SPRN_PID1,r6
- mtspr SPRN_PID2,r6
-
-/* 5. Invalidate mapping we started in */
-2:
- lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
- rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
- mtspr SPRN_MAS0,r7
- tlbre
- mfspr r6,SPRN_MAS1
- rlwinm r6,r6,0,2,0 /* clear IPROT */
- mtspr SPRN_MAS1,r6
- tlbwe
- /* Invalidate TLB1 */
- li r9,0x0c
- tlbivax 0,r9
- TLBSYNC
-
-/* The mapping only needs to be cache-coherent on SMP */
-#ifdef CONFIG_SMP
-#define M_IF_SMP MAS2_M
-#else
-#define M_IF_SMP 0
-#endif
-
-/* 6. Setup KERNELBASE mapping in TLB1[0] */
- lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
- mtspr SPRN_MAS0,r6
- lis r6,(MAS1_VALID|MAS1_IPROT)@h
- ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
- mtspr SPRN_MAS1,r6
- lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
- ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
- mtspr SPRN_MAS2,r6
- mtspr SPRN_MAS3,r8
- tlbwe
-
-/* 7. Jump to KERNELBASE mapping */
- lis r6,(KERNELBASE & ~0xfff)@h
- ori r6,r6,(KERNELBASE & ~0xfff)@l
- lis r7,MSR_KERNEL@h
- ori r7,r7,MSR_KERNEL@l
- bl 1f /* Find our address */
-1: mflr r9
- rlwimi r6,r9,0,20,31
- addi r6,r6,(2f - 1b)
- add r6, r6, r25
- mtspr SPRN_SRR0,r6
- mtspr SPRN_SRR1,r7
- rfi /* start execution out of TLB1[0] entry */
-
-/* 8. Clear out the temp mapping */
-2:
- /* Invalidate TLB0 */
- li r9,0x04
- tlbivax 0,r9
- TLBSYNC
+#include "fsl_booke_entry_mapping.S"
/* Establish the interrupt vector offsets */
SET_IVOR(0, CriticalInput);
--
1.6.2.5
^ permalink raw reply related
* [PATCH 3/5] powerpc/head fsl: replace a hardcoded constant
From: Sebastian Andrzej Siewior @ 2010-01-15 16:41 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Sebastian Andrzej Siewior
In-Reply-To: <1263573697-17839-1-git-send-email-linuxppc-dev@ml.breakpoint.cc>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
24 is offset between the opcode past bl and past rfi. This makes it more
obvious.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
arch/powerpc/kernel/head_fsl_booke.S | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index cc76952..445eddd 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -211,11 +211,11 @@ skpinv: addi r6,r6,1 /* Increment */
bl 1f /* Find our address */
1: mflr r9
rlwimi r7,r9,0,20,31
- addi r7,r7,24
+ addi r7,r7,(2f - 1b)
mtspr SPRN_SRR0,r7
mtspr SPRN_SRR1,r6
rfi
-
+2:
/* 4. Clear out PIDs & Search info */
li r6,0
mtspr SPRN_MAS6,r6
--
1.6.2.5
^ permalink raw reply related
* [PATCH 1/5] powerpc/head fsl: fix the case where we are not in the first page
From: Sebastian Andrzej Siewior @ 2010-01-15 16:41 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Sebastian Andrzej Siewior
In-Reply-To: <1263573697-17839-1-git-send-email-linuxppc-dev@ml.breakpoint.cc>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
During boot we change the mapping a few times until we have a "defined"
mapping. During this procedure a small 4KiB mapping is created and after
that one a 64MiB. Currently the offset of the 4KiB page in that we run
is zero because the complete startup up code is in first page which
starts at RPN zero.
If the code is recycled and moved to another location then its execution
will fail because the start address in the 64 MiB mapping is computed
wrongly. It does not consider the offset to the page from the begin of
the memory.
This patch fixes this. Usually (system boot) r25 is zero so this does
not change anything unless the code is recycled.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
arch/powerpc/kernel/head_fsl_booke.S | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 7f4bd7f..799ddbe 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -275,6 +275,7 @@ skpinv: addi r6,r6,1 /* Increment */
1: mflr r9
rlwimi r6,r9,0,20,31
addi r6,r6,(2f - 1b)
+ add r6, r6, r25
mtspr SPRN_SRR0,r6
mtspr SPRN_SRR1,r7
rfi /* start execution out of TLB1[0] entry */
--
1.6.2.5
^ permalink raw reply related
* Kexec support for FSL-BookE, take two
From: Sebastian Andrzej Siewior @ 2010-01-15 16:41 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
This is take two :)
SMP support did not work in the first one and due to the lack of a working
SMP machine it is still absent. I took the e500v1 problem into account and
the result is that I now use multiple 256MiB mappings.
The final mapping covers the first 2GiB so the part of the highmem should
be also covered and not just kernel memory.
The first three patches prepare the entry code to work outside of the
first page. Patch 4 simply moves code and finally patch 5 implements the
kexec functionality.
Sebastian
^ permalink raw reply
* [PATCH 2/5] powerpc/head fsl: move the temp 4KiB mapping to TLB0
From: Sebastian Andrzej Siewior @ 2010-01-15 16:41 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Sebastian Andrzej Siewior
In-Reply-To: <1263573697-17839-1-git-send-email-linuxppc-dev@ml.breakpoint.cc>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Right now the setup code takes ESEL of the current mapping and puts the
temporary into ESEL (old_ESEL & 1 ) + 1 which is either one or two.
This is actually not required since all slots in TLB0 are invalid by now
and can be used.
This patch moved the temp mapping to TLB0, ESEL[0]. The invalidation of
TLB0 does not care about IPPROT so that part can go as well.
The benefit is that now the setup code may set every slot of TLB1 while
before that it was not allowed to touch ESEL one or two depending on the
old_ESEL.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
arch/powerpc/kernel/head_fsl_booke.S | 20 +++++---------------
1 files changed, 5 insertions(+), 15 deletions(-)
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 799ddbe..cc76952 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -165,8 +165,6 @@ skpinv: addi r6,r6,1 /* Increment */
TLBSYNC
/* 3. Setup a temp mapping and jump to it */
- andi. r5, r3, 0x1 /* Find an entry not used and is non-zero */
- addi r5, r5, 0x1
lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
mtspr SPRN_MAS0,r7
@@ -194,12 +192,11 @@ skpinv: addi r6,r6,1 /* Increment */
ori r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
/* Just modify the entry ID and EPN for the temp mapping */
- lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
- rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
+ li r7, 0 /* Set MAS0(TLBSEL) = 0 | ESEL(0) */
mtspr SPRN_MAS0,r7
xori r6,r4,1 /* Setup TMP mapping in the other Address space */
slwi r6,r6,12
- oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h
+ oris r6,r6,(MAS1_VALID)@h
ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
mtspr SPRN_MAS1,r6
mfspr r6,SPRN_MAS2
@@ -281,16 +278,9 @@ skpinv: addi r6,r6,1 /* Increment */
rfi /* start execution out of TLB1[0] entry */
/* 8. Clear out the temp mapping */
-2: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
- rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
- mtspr SPRN_MAS0,r7
- tlbre
- mfspr r8,SPRN_MAS1
- rlwinm r8,r8,0,2,0 /* clear IPROT */
- mtspr SPRN_MAS1,r8
- tlbwe
- /* Invalidate TLB1 */
- li r9,0x0c
+2:
+ /* Invalidate TLB0 */
+ li r9,0x04
tlbivax 0,r9
TLBSYNC
--
1.6.2.5
^ permalink raw reply related
* Re: Kexec support for FSL-BookE, take two
From: Kumar Gala @ 2010-01-15 17:53 UTC (permalink / raw)
To: Sebastian Andrzej Siewior; +Cc: linuxppc-dev
In-Reply-To: <1263573697-17839-1-git-send-email-linuxppc-dev@ml.breakpoint.cc>
On Jan 15, 2010, at 10:41 AM, Sebastian Andrzej Siewior wrote:
> This is take two :)
> SMP support did not work in the first one and due to the lack of a =
working
> SMP machine it is still absent. I took the e500v1 problem into account =
and
> the result is that I now use multiple 256MiB mappings.
> The final mapping covers the first 2GiB so the part of the highmem =
should
> be also covered and not just kernel memory.
>=20
> The first three patches prepare the entry code to work outside of the
> first page. Patch 4 simply moves code and finally patch 5 implements =
the
> kexec functionality.
What do you think we need for SMP support? I'm happy to test out on SMP =
HW (8572)
- k=
^ permalink raw reply
* Re: Kexec support for FSL-BookE, take two
From: Sebastian Andrzej Siewior @ 2010-01-15 19:23 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Sebastian Andrzej Siewior
In-Reply-To: <80DDCCCD-D62C-4A66-AA8B-E0937266AF55@kernel.crashing.org>
* Kumar Gala | 2010-01-15 11:53:13 [-0600]:
>On Jan 15, 2010, at 10:41 AM, Sebastian Andrzej Siewior wrote:
>
>> This is take two :)
>> SMP support did not work in the first one and due to the lack of a working
>> SMP machine it is still absent. I took the e500v1 problem into account and
>> the result is that I now use multiple 256MiB mappings.
>> The final mapping covers the first 2GiB so the part of the highmem should
>> be also covered and not just kernel memory.
>>
>> The first three patches prepare the entry code to work outside of the
>> first page. Patch 4 simply moves code and finally patch 5 implements the
>> kexec functionality.
>
>What do you think we need for SMP support? I'm happy to test out on SMP HW (8572)
Depends on how we want to do it :)
X86 for instance disables all "other" CPUs in machine_shutdown().
Therefore during machine_kexec() they are off and are bootstraped again
during system boot.
PPC64 doesn't do this that way. They call smp_call_function() witch puts
the CPU into real mode and let them spin in a "save" state until they
get released them from this state.
If we are able to disable the CPU and bootstrap it from scratch than I
guess we could do the way x86 does it.
If the CPU keeps the TLB/MMU data after reactivated (what I assume) than we
have to do the same thing that ppc64 does:
- let the other CPU have the also the identical mapping
- spin in a save state in kernel, then purgatory. I guess I should
revisit ppc64 code for details :)
- update the device tree so kernel can kick the other CPU during boot.
>
>- k
Sebastian
^ permalink raw reply
* openpic specification
From: gshan @ 2010-01-16 10:00 UTC (permalink / raw)
To: linuxppc-dev
I ever searched openpic specification on google for several times, but
unfortunately nothing found.
Could anybody point me where I can get the openpic specification?
The source code seems being from IBM: arch/powerpc/sysdev/mpic.c
Thanks in advance,
Gavin
^ permalink raw reply
* [PATCH] perf_event: e500 support
From: Scott Wood @ 2010-01-15 21:43 UTC (permalink / raw)
To: linuxppc-dev
This implements perf_event support for the Freescale embedded performance
monitor, based on the existing perf_event.c that supports server/classic
chips. Eventually we may want to factor out some of the common bits.
Some limitations:
- No threshold support -- need to figure out how to represent it in
the event struct from userspace.
- Performance monitor interrupts are regular EE interrupts, and thus you
can't profile places with interrupts disabled. We may want to implement
soft IRQ-disabling on 32-bit, with perfmon interrupts exempted and treated
as NMIs.
- When trying to schedule multiple event groups at once, and using
restricted events, situations could arise where scheduling fails even
though it would be possible. Consider three groups, each with two events.
One group has restricted events, the others don't. The two non-restricted
groups are scheduled, then one is removed, which happens to occupy the two
counters that can't do restricted events. The remaining non-restricted
group will not be moved to the non-restricted-capable counters to make
room if the restricted group tries to be scheduled. Since thresholds are
not yet supported (though you can use the events with a threshold of
zero), and threshold events are the only restricted events, this seems
like a low priority issue.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
I did some basic testing with "perf top" and "perf stat"; the results looked
reasonable.
arch/powerpc/include/asm/perf_event.h | 35 ++-
arch/powerpc/include/asm/reg_fsl_emb.h | 2 +-
arch/powerpc/kernel/Makefile | 5 +-
arch/powerpc/kernel/cputable.c | 2 +-
arch/powerpc/kernel/e500-pmu.c | 120 ++++++
arch/powerpc/kernel/perf_event_fsl_emb.c | 658 ++++++++++++++++++++++++++++++
arch/powerpc/platforms/Kconfig.cputype | 10 +
7 files changed, 828 insertions(+), 4 deletions(-)
create mode 100644 arch/powerpc/kernel/e500-pmu.c
create mode 100644 arch/powerpc/kernel/perf_event_fsl_emb.c
diff --git a/arch/powerpc/include/asm/perf_event.h b/arch/powerpc/include/asm/perf_event.h
index 3288ce3..2fd2781 100644
--- a/arch/powerpc/include/asm/perf_event.h
+++ b/arch/powerpc/include/asm/perf_event.h
@@ -2,6 +2,7 @@
* Performance event support - PowerPC-specific definitions.
*
* Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ * Copyright 2010 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -12,6 +13,36 @@
#include <asm/hw_irq.h>
+#ifdef CONFIG_FSL_EMB_PERFMON
+#define MAX_HWEVENTS 4
+
+/* event flags */
+#define FSL_EMB_EVENT_VALID 1
+#define FSL_EMB_EVENT_RESTRICTED 2
+
+struct power_pmu {
+ const char *name;
+ int n_counter; /* total number of counters */
+
+ /*
+ * The number of contiguous counters starting at zero that
+ * can hold restricted events, or zero if there are no
+ * restricted events.
+ *
+ * This isn't a very flexible method of expressing constraints,
+ * but it's very simple and is adequate for existing chips.
+ */
+ int n_restricted;
+
+ int (*get_event_flags)(u64 event_id);
+
+ 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];
+};
+#else
#define MAX_HWEVENTS 8
#define MAX_EVENT_ALTERNATIVES 8
#define MAX_LIMITED_HWCOUNTERS 2
@@ -55,7 +86,6 @@ struct power_pmu {
#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);
@@ -108,3 +138,6 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
* If an event_id is not subject to the constraint expressed by a particular
* field, then it will have 0 in both the mask and value for that field.
*/
+#endif /* !CONFIG_FSL_EMB_PERFMON */
+
+extern int register_power_pmu(struct power_pmu *);
diff --git a/arch/powerpc/include/asm/reg_fsl_emb.h b/arch/powerpc/include/asm/reg_fsl_emb.h
index 0de404d..77bb71c 100644
--- a/arch/powerpc/include/asm/reg_fsl_emb.h
+++ b/arch/powerpc/include/asm/reg_fsl_emb.h
@@ -31,7 +31,7 @@
#define PMLCA_FCM0 0x08000000 /* Freeze when PMM==0 */
#define PMLCA_CE 0x04000000 /* Condition Enable */
-#define PMLCA_EVENT_MASK 0x007f0000 /* Event field */
+#define PMLCA_EVENT_MASK 0x00ff0000 /* Event field */
#define PMLCA_EVENT_SHIFT 16
#define PMRN_PMLCB0 0x110 /* PM Local Control B0 */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index c002b04..ab98a88 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -98,7 +98,10 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
-obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o perf_callchain.o
+obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o
+obj-$(CONFIG_FSL_EMB_PERF_EVENT) += perf_event_fsl_emb.o
+obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o
+obj-$(CONFIG_PERF_EVENTS) += perf_callchain.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
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 2fc82ba..8af4949 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1808,7 +1808,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.icache_bsize = 64,
.dcache_bsize = 64,
.num_pmcs = 4,
- .oprofile_cpu_type = "ppc/e500", /* xxx - galak, e500mc? */
+ .oprofile_cpu_type = "ppc/e500mc",
.oprofile_type = PPC_OPROFILE_FSL_EMB,
.cpu_setup = __setup_cpu_e500mc,
.machine_check = machine_check_e500,
diff --git a/arch/powerpc/kernel/e500-pmu.c b/arch/powerpc/kernel/e500-pmu.c
new file mode 100644
index 0000000..196f82c
--- /dev/null
+++ b/arch/powerpc/kernel/e500-pmu.c
@@ -0,0 +1,120 @@
+/*
+ * Performance counter support for e500 family processors.
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/string.h>
+#include <linux/perf_event.h>
+#include <asm/reg.h>
+#include <asm/cputable.h>
+
+/*
+ * Map of generic hardware event types to hardware events
+ * Zero if unsupported
+ */
+static int e500_generic_events[] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = 1,
+ [PERF_COUNT_HW_INSTRUCTIONS] = 2,
+ [PERF_COUNT_HW_CACHE_MISSES] = 41, /* Data L1 cache reloads */
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 12,
+ [PERF_COUNT_HW_BRANCH_MISSES] = 15,
+};
+
+#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 e500_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+ /*
+ * D-cache misses are not split into read/write/prefetch;
+ * use raw event 41.
+ */
+ [C(L1D)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 27, 0 },
+ [C(OP_WRITE)] = { 28, 0 },
+ [C(OP_PREFETCH)] = { 29, 0 },
+ },
+ [C(L1I)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 2, 60 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { 0, 0 },
+ },
+ /*
+ * Assuming LL means L2, it's not a good match for this model.
+ * It allocates only on L1 castout or explicit prefetch, and
+ * does not have separate read/write events (but it does have
+ * separate instruction/data events).
+ */
+ [C(LL)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 0, 0 },
+ [C(OP_WRITE)] = { 0, 0 },
+ [C(OP_PREFETCH)] = { 0, 0 },
+ },
+ /*
+ * There are data/instruction MMU misses, but that's a miss on
+ * the chip's internal level-one TLB which is probably not
+ * what the user wants. Instead, unified level-two TLB misses
+ * are reported here.
+ */
+ [C(DTLB)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 26, 66 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
+ [C(BPU)] = { /* RESULT_ACCESS RESULT_MISS */
+ [C(OP_READ)] = { 12, 15 },
+ [C(OP_WRITE)] = { -1, -1 },
+ [C(OP_PREFETCH)] = { -1, -1 },
+ },
+};
+
+static int num_events = 128;
+
+static int e500_get_event_flags(u64 event_id)
+{
+ int ret;
+
+ if (event_id >= num_events)
+ return 0;
+
+ ret = FSL_EMB_EVENT_VALID;
+
+ if (event_id >= 76 && event_id <= 81)
+ ret |= FSL_EMB_EVENT_RESTRICTED;
+
+ return ret;
+}
+
+static struct power_pmu e500_pmu = {
+ .name = "e500 family",
+ .n_counter = 4,
+ .n_restricted = 2,
+ .get_event_flags = e500_get_event_flags,
+ .n_generic = ARRAY_SIZE(e500_generic_events),
+ .generic_events = e500_generic_events,
+ .cache_events = &e500_cache_events,
+};
+
+static int init_e500_pmu(void)
+{
+ if (!cur_cpu_spec->oprofile_cpu_type)
+ return -ENODEV;
+
+ if (!strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/e500mc"))
+ num_events = 256;
+ else if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/e500"))
+ return -ENODEV;
+
+ return register_power_pmu(&e500_pmu);
+}
+
+arch_initcall(init_e500_pmu);
diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c
new file mode 100644
index 0000000..3f6cf39
--- /dev/null
+++ b/arch/powerpc/kernel/perf_event_fsl_emb.c
@@ -0,0 +1,658 @@
+/*
+ * Performance event support - Freescale Embedded Performance Monitor
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/perf_event.h>
+#include <linux/percpu.h>
+#include <linux/hardirq.h>
+#include <asm/reg_fsl_emb.h>
+#include <asm/pmc.h>
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+#include <asm/ptrace.h>
+
+struct cpu_hw_events {
+ int n_events;
+ int disabled;
+ u8 pmcs_enabled;
+ struct perf_event *event[MAX_HWEVENTS];
+};
+static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+
+static struct power_pmu *ppmu;
+
+/* Number of perf_events counting hardware events */
+static atomic_t num_events;
+/* Used to avoid races in calling reserve/release_pmc_hardware */
+static DEFINE_MUTEX(pmc_reserve_mutex);
+
+/*
+ * 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)
+{
+#ifdef __powerpc64__
+ return !regs->softe;
+#else
+ return 0;
+#endif
+}
+
+static void perf_event_interrupt(struct pt_regs *regs);
+
+/*
+ * Read one performance monitor counter (PMC).
+ */
+static unsigned long read_pmc(int idx)
+{
+ unsigned long val;
+
+ switch (idx) {
+ case 0:
+ val = mfpmr(PMRN_PMC0);
+ break;
+ case 1:
+ val = mfpmr(PMRN_PMC1);
+ break;
+ case 2:
+ val = mfpmr(PMRN_PMC2);
+ break;
+ case 3:
+ val = mfpmr(PMRN_PMC3);
+ break;
+ default:
+ printk(KERN_ERR "oops trying to read PMC%d\n", idx);
+ val = 0;
+ }
+ return val;
+}
+
+/*
+ * Write one PMC.
+ */
+static void write_pmc(int idx, unsigned long val)
+{
+ switch (idx) {
+ case 0:
+ mtpmr(PMRN_PMC0, val);
+ break;
+ case 1:
+ mtpmr(PMRN_PMC1, val);
+ break;
+ case 2:
+ mtpmr(PMRN_PMC2, val);
+ break;
+ case 3:
+ mtpmr(PMRN_PMC3, val);
+ break;
+ default:
+ printk(KERN_ERR "oops trying to write PMC%d\n", idx);
+ }
+
+ isync();
+}
+
+/*
+ * Write one local control A register
+ */
+static void write_pmlca(int idx, unsigned long val)
+{
+ switch (idx) {
+ case 0:
+ mtpmr(PMRN_PMLCA0, val);
+ break;
+ case 1:
+ mtpmr(PMRN_PMLCA1, val);
+ break;
+ case 2:
+ mtpmr(PMRN_PMLCA2, val);
+ break;
+ case 3:
+ mtpmr(PMRN_PMLCA3, val);
+ break;
+ default:
+ printk(KERN_ERR "oops trying to write PMLCA%d\n", idx);
+ }
+
+ isync();
+}
+
+/*
+ * Write one local control B register
+ */
+static void write_pmlcb(int idx, unsigned long val)
+{
+ switch (idx) {
+ case 0:
+ mtpmr(PMRN_PMLCB0, val);
+ break;
+ case 1:
+ mtpmr(PMRN_PMLCB1, val);
+ break;
+ case 2:
+ mtpmr(PMRN_PMLCB2, val);
+ break;
+ case 3:
+ mtpmr(PMRN_PMLCB3, val);
+ break;
+ default:
+ printk(KERN_ERR "oops trying to write PMLCB%d\n", idx);
+ }
+
+ isync();
+}
+
+static void power_pmu_read(struct perf_event *event)
+{
+ s64 val, delta, prev;
+
+ /*
+ * Performance monitor interrupts come even when interrupts
+ * are soft-disabled, as long as interrupts are hard-enabled.
+ * Therefore we treat them like NMIs.
+ */
+ do {
+ prev = atomic64_read(&event->hw.prev_count);
+ barrier();
+ val = read_pmc(event->hw.idx);
+ } while (atomic64_cmpxchg(&event->hw.prev_count, prev, val) != prev);
+
+ /* The counters are only 32 bits wide */
+ delta = (val - prev) & 0xfffffffful;
+ atomic64_add(delta, &event->count);
+ atomic64_sub(delta, &event->hw.period_left);
+}
+
+/*
+ * Disable all events to prevent PMU interrupts and to allow
+ * events to be added or removed.
+ */
+void hw_perf_disable(void)
+{
+ struct cpu_hw_events *cpuhw;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ cpuhw = &__get_cpu_var(cpu_hw_events);
+
+ if (!cpuhw->disabled) {
+ cpuhw->disabled = 1;
+
+ /*
+ * Check if we ever enabled the PMU on this cpu.
+ */
+ if (!cpuhw->pmcs_enabled) {
+ ppc_enable_pmcs();
+ cpuhw->pmcs_enabled = 1;
+ }
+
+ if (atomic_read(&num_events)) {
+ /*
+ * Set the 'freeze all counters' bit, and disable
+ * interrupts. The barrier is to make sure the
+ * mtpmr has been executed and the PMU has frozen
+ * the events before we return.
+ */
+
+ mtpmr(PMRN_PMGC0, PMGC0_FAC);
+ isync();
+ }
+ }
+ local_irq_restore(flags);
+}
+
+/*
+ * Re-enable all events if disable == 0.
+ * If we were previously disabled and events were added, then
+ * put the new config on the PMU.
+ */
+void hw_perf_enable(void)
+{
+ struct cpu_hw_events *cpuhw;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ cpuhw = &__get_cpu_var(cpu_hw_events);
+ if (!cpuhw->disabled)
+ goto out;
+
+ cpuhw->disabled = 0;
+ ppc_set_pmu_inuse(cpuhw->n_events != 0);
+
+ if (cpuhw->n_events > 0) {
+ mtpmr(PMRN_PMGC0, PMGC0_PMIE | PMGC0_FCECE);
+ isync();
+ }
+
+ out:
+ local_irq_restore(flags);
+}
+
+static int collect_events(struct perf_event *group, int max_count,
+ struct perf_event *ctrs[])
+{
+ int n = 0;
+ struct perf_event *event;
+
+ if (!is_software_event(group)) {
+ if (n >= max_count)
+ return -1;
+ ctrs[n] = group;
+ n++;
+ }
+ list_for_each_entry(event, &group->sibling_list, group_entry) {
+ if (!is_software_event(event) &&
+ event->state != PERF_EVENT_STATE_OFF) {
+ if (n >= max_count)
+ return -1;
+ ctrs[n] = event;
+ n++;
+ }
+ }
+ return n;
+}
+
+/* perf must be disabled, context locked on entry */
+static int power_pmu_enable(struct perf_event *event)
+{
+ struct cpu_hw_events *cpuhw;
+ int ret = -EAGAIN;
+ int num_counters = ppmu->n_counter;
+ u64 val;
+ int i;
+
+ cpuhw = &get_cpu_var(cpu_hw_events);
+
+ if (event->hw.config & FSL_EMB_EVENT_RESTRICTED)
+ num_counters = ppmu->n_restricted;
+
+ /*
+ * Allocate counters from top-down, so that restricted-capable
+ * counters are kept free as long as possible.
+ */
+ for (i = num_counters - 1; i >= 0; i--) {
+ if (cpuhw->event[i])
+ continue;
+
+ break;
+ }
+
+ if (i < 0)
+ goto out;
+
+ event->hw.idx = i;
+ cpuhw->event[i] = event;
+ ++cpuhw->n_events;
+
+ val = 0;
+ if (event->hw.sample_period) {
+ s64 left = atomic64_read(&event->hw.period_left);
+ if (left < 0x80000000L)
+ val = 0x80000000L - left;
+ }
+ atomic64_set(&event->hw.prev_count, val);
+ write_pmc(i, val);
+ perf_event_update_userpage(event);
+
+ write_pmlcb(i, event->hw.event_base);
+ write_pmlca(i, event->hw.config_base);
+
+ ret = 0;
+ out:
+ put_cpu_var(cpu_hw_events);
+ return ret;
+}
+
+/* perf must be disabled, context locked on entry */
+static void power_pmu_disable(struct perf_event *event)
+{
+ struct cpu_hw_events *cpuhw;
+ int i = event->hw.idx;
+
+ if (i < 0)
+ goto out;
+
+ power_pmu_read(event);
+
+ cpuhw = &get_cpu_var(cpu_hw_events);
+
+ WARN_ON(event != cpuhw->event[event->hw.idx]);
+
+ write_pmlca(i, 0);
+ write_pmc(i, 0);
+
+ cpuhw->event[i] = NULL;
+ event->hw.idx = -1;
+
+ /*
+ * TODO: if at least one restricted event exists, and we
+ * just freed up a non-restricted-capable counter, and
+ * there is a restricted-capable counter occupied by
+ * a non-restricted event, migrate that event to the
+ * vacated counter.
+ */
+
+ cpuhw->n_events--;
+
+ out:
+ put_cpu_var(cpu_hw_events);
+}
+
+/*
+ * Re-enable interrupts on a event after they were throttled
+ * because they were coming too fast.
+ *
+ * Context is locked on entry, but perf is not disabled.
+ */
+static void power_pmu_unthrottle(struct perf_event *event)
+{
+ s64 val, left;
+ unsigned long flags;
+
+ if (event->hw.idx < 0 || !event->hw.sample_period)
+ return;
+ local_irq_save(flags);
+ perf_disable();
+ power_pmu_read(event);
+ left = event->hw.sample_period;
+ event->hw.last_period = left;
+ val = 0;
+ if (left < 0x80000000L)
+ val = 0x80000000L - left;
+ write_pmc(event->hw.idx, val);
+ atomic64_set(&event->hw.prev_count, val);
+ atomic64_set(&event->hw.period_left, left);
+ perf_event_update_userpage(event);
+ perf_enable();
+ local_irq_restore(flags);
+}
+
+static struct pmu power_pmu = {
+ .enable = power_pmu_enable,
+ .disable = power_pmu_disable,
+ .read = power_pmu_read,
+ .unthrottle = power_pmu_unthrottle,
+};
+
+/*
+ * Release the PMU if this is the last perf_event.
+ */
+static void hw_perf_event_destroy(struct perf_event *event)
+{
+ if (!atomic_add_unless(&num_events, -1, 1)) {
+ mutex_lock(&pmc_reserve_mutex);
+ if (atomic_dec_return(&num_events) == 0)
+ release_pmc_hardware();
+ mutex_unlock(&pmc_reserve_mutex);
+ }
+}
+
+/*
+ * Translate a generic cache event_id config to a raw event_id code.
+ */
+static int hw_perf_cache_event(u64 config, u64 *eventp)
+{
+ unsigned long type, op, result;
+ int ev;
+
+ if (!ppmu->cache_events)
+ return -EINVAL;
+
+ /* unpack config */
+ type = config & 0xff;
+ op = (config >> 8) & 0xff;
+ result = (config >> 16) & 0xff;
+
+ if (type >= PERF_COUNT_HW_CACHE_MAX ||
+ op >= PERF_COUNT_HW_CACHE_OP_MAX ||
+ result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+ return -EINVAL;
+
+ ev = (*ppmu->cache_events)[type][op][result];
+ if (ev == 0)
+ return -EOPNOTSUPP;
+ if (ev == -1)
+ return -EINVAL;
+ *eventp = ev;
+ return 0;
+}
+
+const struct pmu *hw_perf_event_init(struct perf_event *event)
+{
+ u64 ev;
+ struct perf_event *events[MAX_HWEVENTS];
+ int n;
+ int err;
+ int num_restricted;
+ int i;
+
+ switch (event->attr.type) {
+ case PERF_TYPE_HARDWARE:
+ ev = event->attr.config;
+ if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
+ return ERR_PTR(-EOPNOTSUPP);
+ ev = ppmu->generic_events[ev];
+ break;
+
+ case PERF_TYPE_HW_CACHE:
+ err = hw_perf_cache_event(event->attr.config, &ev);
+ if (err)
+ return ERR_PTR(err);
+ break;
+
+ case PERF_TYPE_RAW:
+ ev = event->attr.config;
+ break;
+
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ event->hw.config = ppmu->get_event_flags(ev);
+ if (!(event->hw.config & FSL_EMB_EVENT_VALID))
+ return ERR_PTR(-EINVAL);
+
+ /*
+ * If this is in a group, check if it can go on with all the
+ * other hardware events in the group. We assume the event
+ * hasn't been linked into its leader's sibling list at this point.
+ */
+ n = 0;
+ if (event->group_leader != event) {
+ n = collect_events(event->group_leader,
+ ppmu->n_counter - 1, events);
+ if (n < 0)
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) {
+ num_restricted = 0;
+ for (i = 0; i < n; i++) {
+ if (events[i]->hw.config & FSL_EMB_EVENT_RESTRICTED)
+ num_restricted++;
+ }
+
+ if (num_restricted >= ppmu->n_restricted)
+ return ERR_PTR(-EINVAL);
+ }
+
+ event->hw.idx = -1;
+
+ event->hw.config_base = PMLCA_CE | PMLCA_FCM1 | ((u32)ev << 16);
+
+ if (event->attr.exclude_user)
+ event->hw.config_base |= PMLCA_FCU;
+ if (event->attr.exclude_kernel)
+ event->hw.config_base |= PMLCA_FCS;
+ if (event->attr.exclude_idle)
+ return ERR_PTR(-ENOTSUPP);
+
+ /*
+ * TODO: thresholds. This will hold PMLCb.
+ * How should thresholds be represented in event->attr?
+ */
+ event->hw.event_base = 0;
+
+ event->hw.last_period = event->hw.sample_period;
+ atomic64_set(&event->hw.period_left, event->hw.last_period);
+
+ /*
+ * See if we need to reserve the PMU.
+ * If no events are currently in use, then we have to take a
+ * mutex to ensure that we don't race with another task doing
+ * reserve_pmc_hardware or release_pmc_hardware.
+ */
+ err = 0;
+ if (!atomic_inc_not_zero(&num_events)) {
+ mutex_lock(&pmc_reserve_mutex);
+ if (atomic_read(&num_events) == 0 &&
+ reserve_pmc_hardware(perf_event_interrupt))
+ err = -EBUSY;
+ else
+ atomic_inc(&num_events);
+ mutex_unlock(&pmc_reserve_mutex);
+
+ mtpmr(PMRN_PMGC0, PMGC0_FAC);
+ isync();
+ }
+ event->destroy = hw_perf_event_destroy;
+
+ if (err)
+ return ERR_PTR(err);
+ return &power_pmu;
+}
+
+/*
+ * A counter has overflowed; update its count and record
+ * 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_event *event, unsigned long val,
+ struct pt_regs *regs, int nmi)
+{
+ u64 period = event->hw.sample_period;
+ s64 prev, delta, left;
+ int record = 0;
+
+ /* we don't have to worry about interrupts here */
+ prev = atomic64_read(&event->hw.prev_count);
+ delta = (val - prev) & 0xfffffffful;
+ atomic64_add(delta, &event->count);
+
+ /*
+ * See if the total period for this event has expired,
+ * and update for the next period.
+ */
+ val = 0;
+ left = atomic64_read(&event->hw.period_left) - delta;
+ if (period) {
+ if (left <= 0) {
+ left += period;
+ if (left <= 0)
+ left = period;
+ record = 1;
+ }
+ if (left < 0x80000000LL)
+ val = 0x80000000LL - left;
+ }
+
+ /*
+ * Finally record data if requested.
+ */
+ if (record) {
+ struct perf_sample_data data = {
+ .period = event->hw.last_period,
+ };
+
+ if (perf_event_overflow(event, nmi, &data, regs)) {
+ /*
+ * Interrupts are coming too fast - throttle them
+ * by setting the event to 0, so it will be
+ * at least 2^30 cycles until the next interrupt
+ * (assuming each event counts at most 2 counts
+ * per cycle).
+ */
+ val = 0;
+ left = ~0ULL >> 1;
+ }
+ }
+
+ write_pmc(event->hw.idx, val);
+ atomic64_set(&event->hw.prev_count, val);
+ atomic64_set(&event->hw.period_left, left);
+ perf_event_update_userpage(event);
+}
+
+static void perf_event_interrupt(struct pt_regs *regs)
+{
+ int i;
+ struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
+ struct perf_event *event;
+ unsigned long val;
+ int found = 0;
+ int nmi;
+
+ nmi = perf_intr_is_nmi(regs);
+ if (nmi)
+ nmi_enter();
+ else
+ irq_enter();
+
+ for (i = 0; i < ppmu->n_counter; ++i) {
+ event = cpuhw->event[i];
+
+ val = read_pmc(i);
+ if ((int)val < 0) {
+ if (event) {
+ /* event has overflowed */
+ found = 1;
+ record_and_restart(event, val, regs, nmi);
+ } else {
+ /*
+ * Disabled counter is negative,
+ * reset it just in case.
+ */
+ write_pmc(i, 0);
+ }
+ }
+ }
+
+ /* PMM will keep counters frozen until we return from the interrupt. */
+ mtmsr(mfmsr() | MSR_PMM);
+ mtpmr(PMRN_PMGC0, PMGC0_PMIE | PMGC0_FCECE);
+ isync();
+
+ if (nmi)
+ nmi_exit();
+ else
+ irq_exit();
+}
+
+void hw_perf_event_setup(int cpu)
+{
+ struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu);
+
+ memset(cpuhw, 0, sizeof(*cpuhw));
+}
+
+int register_power_pmu(struct power_pmu *pmu)
+{
+ if (ppmu)
+ return -EBUSY; /* something's already registered */
+
+ ppmu = pmu;
+ pr_info("%s performance monitor hardware support registered\n",
+ pmu->name);
+
+ return 0;
+}
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index fa0f690..f78d629 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -144,6 +144,16 @@ config FSL_EMB_PERFMON
and some e300 cores (c3 and c4). Select this only if your
core supports the Embedded Performance Monitor APU
+config FSL_EMB_PERF_EVENT
+ bool
+ depends on FSL_EMB_PERFMON && PERF_EVENTS
+ default y
+
+config FSL_EMB_PERF_EVENT_E500
+ bool
+ depends on FSL_EMB_PERF_EVENT && E500
+ default y
+
config 4xx
bool
depends on 40x || 44x
--
1.6.4.4
^ permalink raw reply related
* Re: openpic specification
From: Kumar Gala @ 2010-01-15 22:04 UTC (permalink / raw)
To: gshan; +Cc: linuxppc-dev
In-Reply-To: <4B518E4B.4010202@alcatel-lucent.com>
On Jan 16, 2010, at 4:00 AM, gshan wrote:
> I ever searched openpic specification on google for several times, but =
unfortunately nothing found.
> Could anybody point me where I can get the openpic specification?
>=20
> The source code seems being from IBM: arch/powerpc/sysdev/mpic.c
While not the openpic spec if you grab any of the Freescale RM for =
MPC85xx chips there will be a chapter on the PIC that is an "openPIC" =
based interrupt controller.
- k=
^ permalink raw reply
* Re: Problem dtb file booting Kernel 2.6.32
From: Hunter Cobbs @ 2010-01-16 3:59 UTC (permalink / raw)
To: Andres Marquez; +Cc: Scott Wood, linuxppc-dev
In-Reply-To: <1263565840.13514.2.camel@localhost.localdomain>
Hi,
If you're going to attempt to use v1 dts, you might want to try to add
* option) any later version.
*/
/dts-v1/;
/ {
to your DTS file. Also, you'll want to prefix all of your hex addresses
with "0x" so, 200000 = 0x200000
Hope that helps,
Hunter
On Fri, 2010-01-15 at 09:30 -0500, Andres F Marquez wrote:
> Hello,
>
> I was able to boot Kernel 2.6.26.8 (using our old dts file from
> Kernel 2.6.25). However, I need to upgrade to a newer Kernel because
> I am having serious problems with the ethernet interface under heavy
> load. I am not sure if it could be a scheduling problem or the network
> driver. CPU usage is low but load average is high (more than 4).
>
> The main difference that I could find is that for newer Kernels the
> /arch/ppc was removed. I also read online that dts version changed
> from 0 to 1 somewhere around Kernel 2.6.27 or so.
>
> Following your instruction, I executed in the LTIB command shell:
>
> LTIB> dtc -I dtb -O dts ../mpc8272ads.dtb
>
> I executed that command passing as argument the old working dtb file.
> I got a dts file which I placed in the new Kernel and compiled.
> Unfortunately, I am still getting the same error.
>
> Attached you can find both dts files.
>
> Thank you.
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: Kexec support for FSL-BookE, take two
From: wilbur.chan @ 2010-01-16 12:35 UTC (permalink / raw)
To: Sebastian Andrzej Siewior; +Cc: linuxppc-dev
In-Reply-To: <1263573697-17839-1-git-send-email-linuxppc-dev@ml.breakpoint.cc>
2010/1/16 Sebastian Andrzej Siewior <linuxppc-dev@ml.breakpoint.cc>:
> This is take two :)
> SMP support did not work in the first one and due to the lack of a working
> SMP machine it is still absent. I took the e500v1 problem into account and
> the result is that I now use multiple 256MiB mappings.
> The final mapping covers the first 2GiB so the part of the highmem should
> be also covered and not just kernel memory.
>
> The first three patches prepare the entry code to work outside of the
> first page. Patch 4 simply moves code and finally patch 5 implements the
> kexec functionality.
Hi, sebastian
Is it possible to avoid setting up the 1:1 mapping but to convert
physical address into virt before relocate , like mips do?
2010/1/16 Kumar Gala <galak@kernel.crashing.org>:
>
> What do you think we need for SMP support? I'm happy to test out on SMP HW (8572)
>
I'm happy to test it too :D
^ permalink raw reply
* Re: Kexec support for FSL-BookE, take two
From: Sebastian Andrzej Siewior @ 2010-01-16 12:52 UTC (permalink / raw)
To: wilbur.chan; +Cc: linuxppc-dev
In-Reply-To: <e997b7421001160435q83f5837rb931f8a16766ce91@mail.gmail.com>
* wilbur.chan | 2010-01-16 20:35:50 [+0800]:
>Is it possible to avoid setting up the 1:1 mapping but to convert
>physical address into virt before relocate , like mips do?
No.
>2010/1/16 Kumar Gala <galak@kernel.crashing.org>:
>
>>
>> What do you think we need for SMP support? I'm happy to test out on SMP HW (8572)
>>
>
>I'm happy to test it too :D
I have a 8572 myself but it is not working reliably right now. I will
try to merge the userland pieces and then I will probably look at SMP.
Sebastian
^ 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