* Re: BUG: NETDEV WATCHDOG -> Badness in gianfar driver?
From: Andy Fleming @ 2007-04-26 18:58 UTC (permalink / raw)
To: Clemens Koller; +Cc: linuxppc-embedded
In-Reply-To: <4630E0F3.10100@anagramm.de>
On Apr 26, 2007, at 12:27, Clemens Koller wrote:
> Hi There!
>
> Any ideas of what could be wrong there? I think there could be a
> problem
> in the gianfar network driver. Or is there a physical problem with
> the PHY
> (a Marvell MV88E1111)?
hard to say which.
> Jan 1 03:43:23 ecam kernel: ------------[ cut here ]------------
> Jan 1 03:43:23 ecam kernel: Badness at c003d3d8 [verbose debug
> info unavailable]
> Jan 1 03:43:23 ecam kernel: Call Trace:
> Jan 1 03:43:23 ecam kernel: [C0355C70] [C0008FE0] show_stack+0x3c/
> 0x194 (unreliable)
> Jan 1 03:43:23 ecam kernel: [C0355CA0] [C0135594] report_bug
> +0xa4/0xac
> Jan 1 03:43:23 ecam kernel: [C0355CB0] [C0003784]
> program_check_exception+0x2b8/0x460
> Jan 1 03:43:23 ecam kernel: [C0355CD0] [C0002908]
> ret_from_except_full+0x0/0x4c
> Jan 1 03:43:23 ecam kernel: [C0355D90] [C017B3CC]
> marvell_ack_interrupt+0x14/0x38
> Jan 1 03:43:23 ecam kernel: [C0355DB0] [C01764A8] stop_gfar+0x54/0xd0
> Jan 1 03:43:23 ecam kernel: [C0355DD0] [C01773D0] gfar_timeout
> +0x5c/0x68
This is a bit confusing. Could you identify where in
marvell_ack_interrupt this is?
Andy
^ permalink raw reply
* Re: BUG: NETDEV WATCHDOG -> Badness in gianfar driver?
From: Matvejchikov Ilya @ 2007-04-26 19:04 UTC (permalink / raw)
To: Clemens Koller; +Cc: linuxppc-embedded
In-Reply-To: <4630E0F3.10100@anagramm.de>
Good Day!
> The system was running fine for many days and weeks without any problems.
> However, just a few minutes ago I noticed a single clicking sound of the harddisk
> (like a head recalibration), so I checked the system.
> I couldn't connect to it via ssh anymore, but via a serial console I got
> at least endless messages as shown below...
> After a reboot, everything looks fine again but the kernel log grew up
> to several MBytes. I pasted the hopefully interesting part below.
>
> Any ideas of what could be wrong there? I think there could be a problem
> in the gianfar network driver. Or is there a physical problem with the PHY
> (a Marvell MV88E1111)?
>
> Any recommendations of how to debug that thingy?
>
> Jan 1 03:43:23 ecam kernel: ------------[ cut here ]------------
> Jan 1 03:43:23 ecam kernel: Badness at c003d3d8 [verbose debug info unavailable]
> Jan 1 03:43:23 ecam kernel: Call Trace:
> Jan 1 03:43:23 ecam kernel: [C0355C70] [C0008FE0] show_stack+0x3c/0x194 (unreliable)
> Jan 1 03:43:23 ecam kernel: [C0355CA0] [C0135594] report_bug+0xa4/0xac
> Jan 1 03:43:23 ecam kernel: [C0355CB0] [C0003784] program_check_exception+0x2b8/0x460
> Jan 1 03:43:23 ecam kernel: [C0355CD0] [C0002908] ret_from_except_full+0x0/0x4c
> Jan 1 03:43:23 ecam kernel: [C0355D90] [C017B3CC] marvell_ack_interrupt+0x14/0x38
> Jan 1 03:43:23 ecam kernel: [C0355DB0] [C01764A8] stop_gfar+0x54/0xd0
> Jan 1 03:43:23 ecam kernel: [C0355DD0] [C01773D0] gfar_timeout+0x5c/0x68
> Jan 1 03:43:23 ecam kernel: [C0355DE0] [C020A060] dev_watchdog+0x110/0x118
> Jan 1 03:43:23 ecam kernel: [C0355E00] [C0024228] run_timer_softirq+0x148/0x1a8
> Jan 1 03:43:23 ecam kernel: [C0355E40] [C002006C] __do_softirq+0x78/0xe4
> Jan 1 03:43:23 ecam kernel: [C0355E70] [C0007054] do_softirq+0x54/0x58
> Jan 1 03:43:23 ecam kernel: [C0355E80] [C001FE4C] irq_exit+0x48/0x58
> Jan 1 03:43:23 ecam kernel: [C0355E90] [C0004000] timer_interrupt+0x17c/0x224
> Jan 1 03:43:23 ecam kernel: [C0355ED0] [C0002954] ret_from_except+0x0/0x18
> Jan 1 03:43:23 ecam kernel: [C0355F90] [C0009FB8] cpu_idle+0xc0/0xd0
> Jan 1 03:43:23 ecam kernel: [C0355FB0] [C0001A7C] rest_init+0x28/0x38
> Jan 1 03:43:23 ecam kernel: [C0355FC0] [C03568E4] start_kernel+0x220/0x29c
> Jan 1 03:43:23 ecam kernel: [C0355FF0] [C0000388] skpinv+0x2b8/0x2f4
> Jan 1 03:43:23 ecam kernel: ------------[ cut here ]------------
> Jan 1 03:43:23 ecam kernel: Badness at c003d3d8 [verbose debug info unavailable]
> Jan 1 03:43:23 ecam kernel: Call Trace:
> Jan 1 03:43:23 ecam kernel: [C0355C70] [C0008FE0] show_stack+0x3c/0x194 (unreliable)
> [...repeating forever...]
> ----- 8< ----- cut here
This is because gfar_timeout() calls stop_gfar() that calls
phy_write() that must not be called from interrupt context. See
comments to this function.
Best regards,
Matvejchikov Ilya.
^ permalink raw reply
* Re: [PATCH v2] [2.6.22] pasemi: cpufreq driver
From: Segher Boessenkool @ 2007-04-26 19:05 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Olof Johansson, linuxppc-dev, egor, paulus, cpufreq
In-Reply-To: <200704261911.22553.arnd@arndb.de>
>> Unfortunately the setting of the current active state is done to an
>> SDC
>> register, while information of the states is in the PMU, so access to
>> both is needed in the driver.
>
> One thing that you could do is to list only this one register of the
> SDC in the reg property, not all of the SDC.
The system-controller node should really describe
all of the system controller. If the Linux driver
needs to access two separate devices, it should
really just do that. Don't try to make things
"simpler" in the device tree.
You probably should map the SDC registers in the
platform startop code, and then have the various
platform drivers use that. Maybe even do an
abstraction ;-)
Segher
^ permalink raw reply
* Re: ML403 and PPC4xx_DMA ?
From: rvk @ 2007-04-26 19:51 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <1177603586.5532.20.camel@localhost>
The core itself for 405 will not have DCR: Device control registers - becau=
se
no device control bus. Have to look at board spec for whether there is a
replacement and what that is. Based on other comments you are on uncertain
ground, likely defining a few things yourself. Interesting that the base
header has a dep for DCRN based on that config. I assume you have UG011 do=
c
from the Xilinx website.=20
Joachim F=C3=B6rster wrote:
>=20
> Hi all,
>=20
> PS: I tried to compile a kernel image with CONFIG_PPC4xx_DMA enabled,
> but gcc complains about missing definitions in ppc4xx_dma.c ... e.g.
> DCRN_DMASR (defined in ibm405.h). Well I guess I have to have
> DCRN_MASR_BASE defined in xparameters_ml403.h .... but defined to what?
>=20
>=20
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>=20
>=20
--=20
View this message in context: http://www.nabble.com/ML403-and-PPC4xx_DMA---=
tf3652591.html#a10207511
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
^ permalink raw reply
* Re: [PATCH v2] [2.6.22] pasemi: cpufreq driver
From: Olof Johansson @ 2007-04-26 20:26 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: linuxppc-dev, egor, paulus, cpufreq
In-Reply-To: <200704261911.22553.arnd@arndb.de>
On Thu, Apr 26, 2007 at 07:11:21PM +0200, Arnd Bergmann wrote:
> On Thursday 26 April 2007, Olof Johansson wrote:
> > SDC is the system and debug controller, it contains a number of smaller
> > devices such as the PIC, the PMU (Gizmo), RNG, and various debug
> > features. Some already have drivers submitted, others will later on.
>
> Oh well, these chips all seem to be the same. On cell, we have solved
> the problem by introducing the 'cbe_regs' helper library that gives
> access to all those miscellaneous registers to the individual device
> drivers, so that not all of them need to scan the device tree for
> the same registers and map them individually.
Not a bad idea, I'll consider it for the future. Most of our devices are
on a pseudo-PCI bus, so it's only a handful that need special register
access. The stuff in the SDC is the biggest exception.
> The problem with an of_platform_driver for this would be that you
> can only have _one_ driver attached to the registers.
>
> > Unfortunately the setting of the current active state is done to an SDC
> > register, while information of the states is in the PMU, so access to
> > both is needed in the driver.
>
> One thing that you could do is to list only this one register of the
> SDC in the reg property, not all of the SDC.
That doesn't make much sense in this case. The register isn't in the
Gizmo.
Having a driver/library for the SDC that the gizmo driver can use is a
good idea, similar to what you've done on cell. I'll try to have that
ready for 2.6.23, but that shouldn't stop this base driver from going
in now.
-Olof
^ permalink raw reply
* Re: [PATCH] Xilinx framebuffer device driver - 2nd version
From: Arnd Bergmann @ 2007-04-26 20:35 UTC (permalink / raw)
To: Andrei Konovalov; +Cc: rick.moleres, linuxppc-embedded
In-Reply-To: <4630F018.3010200@ru.mvista.com>
> @@ -118,6 +118,12 @@ struct xilinxfb_drvdata {
> #define to_xilinxfb_drvdata(_info) \
> container_of(_info, struct xilinxfb_drvdata, info)
>
> +#define xilinx_fb_out_be32(driverdata, offset, val) \
> + if (driverdata->use_dcr) \
> + mtdcr(driverdata->regs_phys + offset, val); \
> + else \
> + out_be32(driverdata->regs + offset, val)
> +
> static int
> xilinx_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
> unsigned transp, struct fb_info *fbi)
This should probably be an inline function, or use do { ... } while (0)
instead, to make it less error-prone, see
http://kernelnewbies.org/FAQ/DoWhile0 for an explanation.
Arnd <><
^ permalink raw reply
* Re: [PATCH v2] [2.6.22] pasemi: cpufreq driver
From: Olof Johansson @ 2007-04-26 20:37 UTC (permalink / raw)
To: Johannes Berg; +Cc: linuxppc-dev, egor, paulus, arnd, cpufreq
In-Reply-To: <1177583160.6814.37.camel@johannes.berg>
On Thu, Apr 26, 2007 at 12:26:00PM +0200, Johannes Berg wrote:
> On Thu, 2007-04-26 at 00:37 -0500, Olof Johansson wrote:
> >
> > + policy->cur = pas_freqs[cur_astate].frequency;
> > + policy->cpus = cpu_possible_map;
>
> That doesn't seem right.
>
> Either, all your processors scale along each other in which case you
> should use cpu_online_map here, or they scale each on their own in which
> case you just set a single bit here.
You can set the requested speed per-processor, but the actual speed
will be the max of them. Because of this, it's less surprising to set
it on both at the same time since then you'll at least know what you're
running at.
So yes, I'll change it to online_map instead of possible_map.
> The generic code works like this:
> CPU 0 is brought online and cpufreq initialised for it
> CPU 1 is brought online and cpufreq initialised for it. if cpus includes
> more than a single bit, cpufreq is linked to the first other CPU in
> policy->cpus and then cpufreq for CPU1 is deinitialised again.
>
> We have the same bug on powermac but for some reason the patch to fix it
> that I posted a long time ago (look for "powermac: fix G5-cpufreq for
> cpu on/offline") wasn't applied yet. Look at it though, it includes a
> comment on what needs to be done.
Hmm, I just tried adding debugging to the cpu_init code, and I'm not
seeing it called more than once (i.e. only for cpu 0). Mind you, I don't
have cpu hotplug support at this time.
-Olof
^ permalink raw reply
* Re: [PATCH v2] [2.6.22] pasemi: cpufreq driver
From: Olof Johansson @ 2007-04-26 20:38 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev, paulus, egor, Arnd Bergmann, cpufreq
In-Reply-To: <c8fb6a47d8be41f856ab9cf19fc3814d@kernel.crashing.org>
On Thu, Apr 26, 2007 at 09:05:59PM +0200, Segher Boessenkool wrote:
> >>Unfortunately the setting of the current active state is done to an
> >>SDC
> >>register, while information of the states is in the PMU, so access to
> >>both is needed in the driver.
> >
> >One thing that you could do is to list only this one register of the
> >SDC in the reg property, not all of the SDC.
>
> The system-controller node should really describe
> all of the system controller. If the Linux driver
> needs to access two separate devices, it should
> really just do that. Don't try to make things
> "simpler" in the device tree.
>
> You probably should map the SDC registers in the
> platform startop code, and then have the various
> platform drivers use that. Maybe even do an
> abstraction ;-)
Yep, it's a good idea to do and I'll look at it for 2.6.23 time frame.
Thanks,
-Olof
^ permalink raw reply
* Re: [PATCH v2] [2.6.22] pasemi: cpufreq driver
From: Arnd Bergmann @ 2007-04-26 20:43 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, egor, paulus, cpufreq
In-Reply-To: <20070426202632.GA17302@lixom.net>
On Thursday 26 April 2007, Olof Johansson wrote:
> Having a driver/library for the SDC that the gizmo driver can use is a
> good idea, similar to what you've done on cell. I'll try to have that
> ready for 2.6.23, but that shouldn't stop this base driver from going
> in now.
Yes, agreed.
Arnd <><
^ permalink raw reply
* Re: [PATCH] [2.6.22] pasemi: hardware rng driver
From: Olof Johansson @ 2007-04-26 20:46 UTC (permalink / raw)
To: Michael Buesch; +Cc: linuxppc-dev, egor
In-Reply-To: <200704261122.03452.mb@bu3sch.de>
Hi Michael,
All good points, fixed in v3 (posted shortly).
Thanks,
-Olof
On Thu, Apr 26, 2007 at 11:22:03AM +0200, Michael Buesch wrote:
> On Wednesday 25 April 2007 22:45:12 Olof Johansson wrote:
> > +static int __devinit rng_probe(struct of_device *ofdev,
> > + const struct of_device_id *match)
> > +{
> > + struct device_node *rng_np;
> > + struct resource res;
> > + int err = 0;
> > +
> > + rng_np = of_find_compatible_node(NULL, "rng", "1682m-rng");
> > + if (!rng_np)
> > + return -ENODEV;
> > +
> > + err = of_address_to_resource(rng_np, 0, &res);
> > + of_node_put(rng_np);
> > +
> > + if (err)
> > + return -EINVAL;
>
> I think EINVAL is not the correct error code. I'd suggest ENODEV.
>
> > + if (!rng_regs)
> > + rng_regs = ioremap(res.start, 0x100);
> > +
> > + if (!rng_regs)
> > + return -EPERM;
>
> I think EPERM is not the correct error code. I'd suggest ENOMEM.
>
> > + printk(KERN_INFO "Registering PA Semi RNG\n");
> > +
> > + return hwrng_register(&pasemi_rng);
>
> Resource leak.
> Please do something like
>
> err = hwrng_register(&pasemi_rng);
> if (err)
> iounmap(rng_regs);
> return err;
>
> > +}
> > +
> > +static int rng_remove(struct of_device *dev)
> > +{
> > + iounmap(rng_regs);
> > + hwrng_unregister(&pasemi_rng);
>
> Swap these to prevent race conditions.
>
> > +
> > + return 0;
> > +}
>
>
>
> --
> Greetings Michael.
^ permalink raw reply
* [PATCH v3] [2.6.22] pasemi: hardware rng driver
From: Olof Johansson @ 2007-04-26 20:59 UTC (permalink / raw)
To: mb; +Cc: linuxppc-dev, egor, arnd
In-Reply-To: <20070426053725.GB23922@lixom.net>
Driver for the on-chip hardware random number generator on PA Semi
PA6T-1682M.
Signed-off-by: Egor Martovetsky <egor@pasemi.com>
Signed-off-by: Olof Johansson <olof@lixom.net>
---
v3:
* error return codes
* iounmap on register fail
* fix iounmap race on remove
v2:
* Moved register pointer to hwrng->priv
* Cleanups (__init/__exit, module_init/exit)
Index: powerpc/drivers/char/hw_random/Kconfig
===================================================================
--- powerpc.orig/drivers/char/hw_random/Kconfig
+++ powerpc/drivers/char/hw_random/Kconfig
@@ -91,3 +91,17 @@ config HW_RANDOM_OMAP
module will be called omap-rng.
If unsure, say Y.
+
+config HW_RANDOM_PASEMI
+ tristate "PA Semi HW Random Number Generator support"
+ depends on HW_RANDOM && PPC_PASEMI
+ default HW_RANDOM
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on PA6T-1682M processor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pasemi-rng.
+
+ If unsure, say Y.
+
Index: powerpc/drivers/char/hw_random/Makefile
===================================================================
--- powerpc.orig/drivers/char/hw_random/Makefile
+++ powerpc/drivers/char/hw_random/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_HW_RANDOM_GEODE) += geode-r
obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
+obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
Index: powerpc/drivers/char/hw_random/pasemi-rng.c
===================================================================
--- /dev/null
+++ powerpc/drivers/char/hw_random/pasemi-rng.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2006-2007 PA Semi, Inc
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * Driver for the PWRficient onchip rng
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+#include <asm/of_platform.h>
+#include <asm/io.h>
+
+#define SDCRNG_CTL_REG 0x00
+#define SDCRNG_CTL_FVLD_M 0x0000f000
+#define SDCRNG_CTL_FVLD_S 12
+#define SDCRNG_CTL_KSZ 0x00000800
+#define SDCRNG_CTL_RSRC_CRG 0x00000010
+#define SDCRNG_CTL_RSRC_RRG 0x00000000
+#define SDCRNG_CTL_CE 0x00000004
+#define SDCRNG_CTL_RE 0x00000002
+#define SDCRNG_CTL_DR 0x00000001
+#define SDCRNG_CTL_SELECT_RRG_RNG (SDCRNG_CTL_RE | SDCRNG_CTL_RSRC_RRG)
+#define SDCRNG_CTL_SELECT_CRG_RNG (SDCRNG_CTL_CE | SDCRNG_CTL_RSRC_CRG)
+#define SDCRNG_VAL_REG 0x20
+
+#define MODULE_NAME "pasemi_rng"
+
+static int pasemi_rng_data_present(struct hwrng *rng)
+{
+ void __iomem *rng_regs = (void __iomem *)rng->priv;
+
+ return (in_le32(rng_regs + SDCRNG_CTL_REG)
+ & SDCRNG_CTL_FVLD_M) ? 1 : 0;
+}
+
+static int pasemi_rng_data_read(struct hwrng *rng, u32 *data)
+{
+ void __iomem *rng_regs = (void __iomem *)rng->priv;
+ *data = in_le32(rng_regs + SDCRNG_VAL_REG);
+ return 4;
+}
+
+static int pasemi_rng_init(struct hwrng *rng)
+{
+ void __iomem *rng_regs = (void __iomem *)rng->priv;
+ u32 ctl;
+
+ ctl = SDCRNG_CTL_DR | SDCRNG_CTL_SELECT_RRG_RNG | SDCRNG_CTL_KSZ;
+ out_le32(rng_regs + SDCRNG_CTL_REG, ctl);
+ out_le32(rng_regs + SDCRNG_CTL_REG, ctl & ~SDCRNG_CTL_DR);
+
+ return 0;
+}
+
+static void pasemi_rng_cleanup(struct hwrng *rng)
+{
+ void __iomem *rng_regs = (void __iomem *)rng->priv;
+ u32 ctl;
+
+ ctl = SDCRNG_CTL_RE | SDCRNG_CTL_CE;
+ out_le32(rng_regs + SDCRNG_CTL_REG,
+ in_le32(rng_regs + SDCRNG_CTL_REG) & ~ctl);
+}
+
+static struct hwrng pasemi_rng = {
+ .name = MODULE_NAME,
+ .init = pasemi_rng_init,
+ .cleanup = pasemi_rng_cleanup,
+ .data_present = pasemi_rng_data_present,
+ .data_read = pasemi_rng_data_read,
+};
+
+static int __devinit rng_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ void __iomem *rng_regs;
+ struct device_node *rng_np = ofdev->node;
+ struct resource res;
+ int err = 0;
+
+ err = of_address_to_resource(rng_np, 0, &res);
+ if (err)
+ return -ENODEV;
+
+ rng_regs = ioremap(res.start, 0x100);
+
+ if (!rng_regs)
+ return -ENOMEM;
+
+ pasemi_rng.priv = (unsigned long)rng_regs;
+
+ printk(KERN_INFO "Registering PA Semi RNG\n");
+
+ err = hwrng_register(&pasemi_rng);
+
+ if (err)
+ iounmap(rng_regs);
+
+ return err;
+}
+
+static int __devexit rng_remove(struct of_device *dev)
+{
+ void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv;
+
+ hwrng_unregister(&pasemi_rng);
+ iounmap(rng_regs);
+
+ return 0;
+}
+
+static struct of_device_id rng_match[] =
+{
+ {
+ .compatible = "1682m-rng",
+ },
+ {},
+};
+
+static struct of_platform_driver rng_driver =
+{
+ .name = "pasemi-rng",
+ .match_table = rng_match,
+ .probe = rng_probe,
+ .remove = rng_remove,
+};
+
+static int __init rng_init(void)
+{
+ return of_register_platform_driver(&rng_driver);
+}
+module_init(rng_init);
+
+static void __exit rng_exit(void)
+{
+ of_unregister_platform_driver(&rng_driver);
+}
+module_exit(rng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>");
+MODULE_DESCRIPTION("H/W RNG driver for PA Semi processor");
^ permalink raw reply
* RE: ML403 and PPC4xx_DMA ?
From: Rick Moleres @ 2007-04-26 21:36 UTC (permalink / raw)
To: Joachim Förster, linuxppc-embedded
In-Reply-To: <1177603586.5532.20.camel@localhost>
Joachim,
The Xilinx PPC405 core does not have an integrated DMA controller.
-----Original Message-----
From: linuxppc-embedded-bounces+moleres=3Dxilinx.com@ozlabs.org =
[mailto:linuxppc-embedded-bounces+moleres=3Dxilinx.com@ozlabs.org] On =
Behalf Of Joachim F=F6rster
Sent: Thursday, April 26, 2007 10:06 AM
To: linuxppc-embedded@ozlabs.org
Subject: ML403 and PPC4xx_DMA ?
Hi all,
I have a question regarding the PowerPC 405 Core on the Xilinx ML403
board and DMA . The Linux kernel has an option called CONFIG_PPC4xx_DMA.
Do all/some PowerPC 4xx Cores have an integrated DMA Controller? I tried
to find some documentation about this DMA Controller in several Xilinx
and IBM manuals which cover the PowerPC 405 Core - but I didn't find
anything.
So, my question is: Does the Virtex-4 FX12 PowerPC 405 Core on the ML403
have such DMA Controller? If yes, is it usable within Linux to transfer
data from RAM to a device's hardware buffers (typical task of a DMA
controller)?
Thanks,
Joachim
PS: I tried to compile a kernel image with CONFIG_PPC4xx_DMA enabled,
but gcc complains about missing definitions in ppc4xx_dma.c ... e.g.
DCRN_DMASR (defined in ibm405.h). Well I guess I have to have
DCRN_MASR_BASE defined in xparameters_ml403.h .... but defined to what?
_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
^ permalink raw reply
* PHY link up/down looping
From: Clint Thomas @ 2007-04-26 21:53 UTC (permalink / raw)
To: linuxppc-embedded
Hello,
Has anybody here had the problem where upon the linux 2.6 kernel
booting, the PHY link seems to be in some kind of auto-negotiating loop
of going up and down? This has been hapenning in my 2.6.19 kernel with a
Marvell PHY (88E1011S). The board i'm working with is similar to the
MPC8555CDS, so i'm using that kernel config for this environment.
=20
Clinton Thomas
^ permalink raw reply
* DMA controllers (about IOAT vs. BestComm)
From: Matt Sealey @ 2007-04-26 22:03 UTC (permalink / raw)
To: ppc-dev
Quickie question, has anyone from the PPC team looked at the work Intel have
done on the generic DMA engine interface and their IOAT driver?
How does it fare for the possibility of adding common PPC DMA controllers
(52xx BestComm, PowerQUICC II/III, MV63xx, Tsi10x..) for the very basic
memcpy style offloads, not to mention the networking stack, any XOR
engines present and so on?
Or did they make it a little too x86-specific?
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
^ permalink raw reply
* Re: [PATCH] Xilinx framebuffer device driver - 2nd version
From: Andrei Konovalov @ 2007-04-26 21:55 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: rick.moleres, linuxppc-embedded
In-Reply-To: <200704262235.22048.arnd@arndb.de>
Arnd Bergmann wrote:
>>@@ -118,6 +118,12 @@ struct xilinxfb_drvdata {
>> #define to_xilinxfb_drvdata(_info) \
>> container_of(_info, struct xilinxfb_drvdata, info)
>>
>>+#define xilinx_fb_out_be32(driverdata, offset, val) \
>>+ if (driverdata->use_dcr) \
>>+ mtdcr(driverdata->regs_phys + offset, val); \
>>+ else \
>>+ out_be32(driverdata->regs + offset, val)
>>+
>> static int
>> xilinx_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
>> unsigned transp, struct fb_info *fbi)
>
>
> This should probably be an inline function, or use do { ... } while (0)
> instead, to make it less error-prone, see
> http://kernelnewbies.org/FAQ/DoWhile0 for an explanation.
>
> Arnd <><
xilinx_fb_out_be32 macro doesn't declare local variables, and is a single "line of code"
in terms of the web page you've referenced. IOW I can't get an example where this macro
would do wrong off the top of my head. Anyway, the do { ... } while (0) is safe and
common, so I'll regenerate the patch to use it.
Thanks a lot for reviewing that stuff!
Best regards,
Andrei
^ permalink raw reply
* Re: Tri-mode auto-negotiation on ML405
From: Andrei Konovalov @ 2007-04-22 14:18 UTC (permalink / raw)
To: Peter Mendham; +Cc: linuxppc-embedded
In-Reply-To: <46278F3A.4070007@computing.dundee.ac.uk>
Hi Peter,
Peter Mendham wrote:
> Andrei Konovalov wrote:
>
>> And I've tried the PHY library (drivers/net/phy/*) introduced by Andy
>> Fleming.
>> Kinda works. [...]
>> Attached is the incomplete adapter.c (with FIFO mode support only) which
>> uses the PHY lib to handle the PHY. Just to illustrate the idea (will
>> post the
>> patch later when it is completed).
>
> Hi Andrei,
>
> I've now had a chance to have a go at the adapter.c you sent properly
> (sorry about the delay). I'm afraid I can't get it to work. I was
> wondering if you could tell me what I'm doing wrong. When I try and
> bring the interface up I get:
> SIOCSIFADDR: No such device
> SIOCSIFNETMASK: No such device
> SIOCSIFBRDADDR: No such device
> SIOCGIFFLAGS: No such device
> route: SIOC[ADD|DEL]RT: No such device
>
> I have included PHYLIB and even tried including support for the Marvell
> PHY. I still get the same. I'm sure I've made a stupid mistake, any ideas?
Has the ethernet device been registered on the platform bus?
There should be a call to platform_device_register()
in arch/ppc/syslib/virtex_devices.c or arch/ppc/platforms/4xx/virtex.c depending
on the kernel tree used and the patches appiled.
Thanks,
Andrei
> Thanks,
> -- Peter
>
>
>
^ permalink raw reply
* [PATCH v3] powerpc: 64K page support for kexec
From: Luke Browning @ 2007-04-26 22:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Olof Johansson, Paul Mackerras,
cbe-oss-dev, Arnd Bergmann, miltonm
Cc: linuxppc-dev, cbe-oss-dev
This patch fixes a couple of kexec problems related to 64K page
support in the kernel. kexec issues a tlbie for each pte. The
parameters for the tlbie are the page size and the virtual address.
Support was missing for the computation of these two parameters
for 64K pages. This patch adds that support.
Signed-off-by: Luke Browning <lukebrowning@us.ibm.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Index: linux-2.6.21-rc4/arch/powerpc/mm/hash_native_64.c
===================================================================
--- linux-2.6.21-rc4.orig/arch/powerpc/mm/hash_native_64.c
+++ linux-2.6.21-rc4/arch/powerpc/mm/hash_native_64.c
@@ -340,31 +340,74 @@ static void native_hpte_invalidate(unsig
local_irq_restore(flags);
}
-/*
- * XXX This need fixing based on page size. It's only used by
- * native_hpte_clear() for now which needs fixing too so they
- * make a good pair...
- */
-static unsigned long slot2va(unsigned long hpte_v, unsigned long slot)
-{
- unsigned long avpn = HPTE_V_AVPN_VAL(hpte_v);
- unsigned long va;
-
- va = avpn << 23;
-
- if (! (hpte_v & HPTE_V_LARGE)) {
- unsigned long vpi, pteg;
+#define LP_SHIFT 12
+#define LP_BITS 8
+#define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT)
+
+static void hpte_decode(hpte_t *hpte, unsigned long slot,
+ int *psize, unsigned long *va)
+{
+ unsigned long hpte_r = hpte->r;
+ unsigned long hpte_v = hpte->v;
+ unsigned long avpn;
+ int i, size, shift, penc, avpnm_bits;
+
+ if (!(hpte_v & HPTE_V_LARGE))
+ size = MMU_PAGE_4K;
+ else {
+ for (i = 0; i < LP_BITS; i++) {
+ if ((hpte_r & LP_MASK(i+1)) == LP_MASK(i+1))
+ break;
+ }
+ penc = LP_MASK(i+1) >> LP_SHIFT;
+ for (size = 0; size < MMU_PAGE_COUNT; size++) {
- pteg = slot / HPTES_PER_GROUP;
- if (hpte_v & HPTE_V_SECONDARY)
- pteg = ~pteg;
+ /* 4K pages are not represented by LP */
+ if (size == MMU_PAGE_4K)
+ continue;
+
+ /* valid entries have a shift value */
+ if (!mmu_psize_defs[size].shift)
+ continue;
- vpi = ((va >> 28) ^ pteg) & htab_hash_mask;
+ if (penc == mmu_psize_defs[size].penc)
+ break;
+ }
+ }
- va |= vpi << PAGE_SHIFT;
+ /*
+ * FIXME, the code below works for 16M, 64K, and 4K pages as these
+ * fall under the p<=23 rules for calculating the virtual address.
+ * In the case of 16M pages, an extra bit is stolen from the AVPN
+ * field to achieve the requisite 24 bits.
+ *
+ * 16G pages are not supported by the code below.
+ */
+ BUG_ON(hpte_v & 0x4000000000000000UL); /* 1T segment */
+ BUG_ON(size == MMU_PAGE_16G);
+ BUG_ON(size == MMU_PAGE_64K_AP);
+
+ shift = mmu_psize_defs[size].shift;
+ if (mmu_psize_defs[size].avpnm)
+ avpnm_bits = __ilog2_u64(mmu_psize_defs[size].avpnm) + 1;
+ else
+ avpnm_bits = 0;
+ if (shift - avpnm_bits <= 23) {
+ avpn = HPTE_V_AVPN_VAL(hpte_v) << 23;
+
+ if (shift < 23) {
+ unsigned long vpi, pteg;
+
+ pteg = slot / HPTES_PER_GROUP;
+ if (hpte_v & HPTE_V_SECONDARY)
+ pteg = ~pteg;
+ vpi = ((avpn >> 28) ^ pteg) & htab_hash_mask;
+ avpn |= (vpi << mmu_psize_defs[size].shift);
+ }
}
- return va;
+ *va = avpn;
+ *psize = size;
}
/*
@@ -374,15 +417,14 @@ static unsigned long slot2va(unsigned lo
*
* TODO: add batching support when enabled. remember, no dynamic memory here,
* athough there is the control page available...
- *
- * XXX FIXME: 4k only for now !
*/
static void native_hpte_clear(void)
{
unsigned long slot, slots, flags;
hpte_t *hptep = htab_address;
- unsigned long hpte_v;
+ unsigned long hpte_v, va;
unsigned long pteg_count;
+ int psize;
pteg_count = htab_hash_mask + 1;
@@ -408,8 +450,9 @@ static void native_hpte_clear(void)
* already hold the native_tlbie_lock.
*/
if (hpte_v & HPTE_V_VALID) {
+ hpte_decode(hptep, slot, &psize, &va);
hptep->v = 0;
- __tlbie(slot2va(hpte_v, slot), MMU_PAGE_4K);
+ __tlbie(va, psize);
}
}
^ permalink raw reply
* Re: [PATCH v3] powerpc: 64K page support for kexec
From: Olof Johansson @ 2007-04-26 22:32 UTC (permalink / raw)
To: Luke Browning
Cc: Arnd Bergmann, miltonm, linuxppc-dev, Paul Mackerras, cbe-oss-dev
In-Reply-To: <1177626236.24866.99.camel@luke-laptop>
On Thu, Apr 26, 2007 at 07:23:56PM -0300, Luke Browning wrote:
> This patch fixes a couple of kexec problems related to 64K page
> support in the kernel. kexec issues a tlbie for each pte. The
> parameters for the tlbie are the page size and the virtual address.
> Support was missing for the computation of these two parameters
> for 64K pages. This patch adds that support.
>
> Signed-off-by: Luke Browning <lukebrowning@us.ibm.com>
> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Olof Johansson <olof@lixom.net>
-Olof
^ permalink raw reply
* [PATCH] cell: cbe_cpufreq cleanup and crash fix
From: Olof Johansson @ 2007-04-26 23:07 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: linuxppc-dev, cbe-oss-dev, Christian Krafft
In-Reply-To: <20070426065644.GA24799@lixom.net>
cbe_cpufreq cleanups:
* comment format
* whitespace
* don't init on non-cell platforms
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: powerpc/arch/powerpc/platforms/cell/cbe_cpufreq.c
===================================================================
--- powerpc.orig/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ powerpc/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -155,7 +155,7 @@ static int set_pmode_reg(int cpu, unsign
}
static int set_pmode(int cpu, unsigned int slow_mode) {
- if(pmi_dev)
+ if (pmi_dev)
return set_pmode_pmi(cpu, slow_mode);
else
return set_pmode_reg(cpu, slow_mode);
@@ -167,7 +167,7 @@ static void cbe_cpufreq_handle_pmi(struc
u8 cpu;
u8 cbe_pmode_new;
- BUG_ON (pmi_msg.type != PMI_TYPE_FREQ_CHANGE);
+ BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE);
cpu = cbe_node_to_cpu(pmi_msg.data1);
cbe_pmode_new = pmi_msg.data2;
@@ -191,7 +191,7 @@ static struct pmi_handler cbe_pmi_handle
* cpufreq functions
*/
-static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy)
+static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
const u32 *max_freqp;
u32 max_freq;
@@ -200,7 +200,7 @@ static int cbe_cpufreq_cpu_init (struct
cpu = of_get_cpu_node(policy->cpu, NULL);
- if(!cpu)
+ if (!cpu)
return -ENODEV;
pr_debug("init cpufreq on CPU %d\n", policy->cpu);
@@ -210,13 +210,13 @@ static int cbe_cpufreq_cpu_init (struct
if (!max_freqp)
return -EINVAL;
- // we need the freq in kHz
+ /* we need the freq in kHz */
max_freq = *max_freqp / 1000;
pr_debug("max clock-frequency is at %u kHz\n", max_freq);
pr_debug("initializing frequency table\n");
- // initialize frequency table
+ /* initialize frequency table */
for (i=0; cbe_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) {
cbe_freqs[i].frequency = max_freq / cbe_freqs[i].index;
pr_debug("%d: %d\n", i, cbe_freqs[i].frequency);
@@ -235,10 +235,10 @@ static int cbe_cpufreq_cpu_init (struct
policy->cpus = cpu_sibling_map[policy->cpu];
#endif
- cpufreq_frequency_table_get_attr (cbe_freqs, policy->cpu);
+ cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
/* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */
- return cpufreq_frequency_table_cpuinfo (policy, cbe_freqs);
+ return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs);
}
static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
@@ -270,7 +270,7 @@ static int cbe_cpufreq_target(struct cpu
freqs.new = cbe_freqs[cbe_pmode_new].frequency;
freqs.cpu = policy->cpu;
- mutex_lock (&cbe_switch_mutex);
+ mutex_lock(&cbe_switch_mutex);
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n",
@@ -303,6 +303,9 @@ static int __init cbe_cpufreq_init(void)
{
struct device_node *np;
+ if (!machine_is(cell))
+ return 0;
+
np = of_find_node_by_type(NULL, "ibm,pmi");
pmi_dev = of_find_device_by_node(np);
@@ -315,7 +318,7 @@ static int __init cbe_cpufreq_init(void)
static void __exit cbe_cpufreq_exit(void)
{
- if(pmi_dev)
+ if (pmi_dev)
pmi_unregister_handler(pmi_dev, &cbe_pmi_handler);
cpufreq_unregister_driver(&cbe_cpufreq_driver);
^ permalink raw reply
* Re: [PATCH 11/13] powerpc: Add DTS file for the Motorola PrPMC2800 platform
From: Mark A. Greer @ 2007-04-26 23:34 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20070426164226.GA13018@ld0162-tx32.am.freescale.net>
On Thu, Apr 26, 2007 at 11:42:26AM -0500, Scott Wood wrote:
> On Wed, Apr 25, 2007 at 05:01:51PM -0700, Mark A. Greer wrote:
> > + chosen {
> > + linux,platform = <1>;
> > + bootargs = "ip=on console=ttyMM0";
> > + linux,stdout-path = "/mv64x60/mpsc@8000";
> > + };
>
> Isn't linux,platform obsolete?
Hmm, yeah, think so. Good catch. Will remove.
Mark
^ permalink raw reply
* Re: [PATCH 11/13] powerpc: Add DTS file for the Motorola PrPMC2800 platform
From: David Gibson @ 2007-04-26 23:37 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20070426164226.GA13018@ld0162-tx32.am.freescale.net>
On Thu, Apr 26, 2007 at 11:42:26AM -0500, Scott Wood wrote:
> On Wed, Apr 25, 2007 at 05:01:51PM -0700, Mark A. Greer wrote:
> > + chosen {
> > + linux,platform = <1>;
> > + bootargs = "ip=on console=ttyMM0";
> > + linux,stdout-path = "/mv64x60/mpsc@8000";
> > + };
>
> Isn't linux,platform obsolete?
Well and truly. Please get rid of it.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH v2] [2.6.22] pasemi: cpufreq driver
From: Segher Boessenkool @ 2007-04-27 0:10 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, paulus, egor, Arnd Bergmann, cpufreq
In-Reply-To: <20070426203802.GC17302@lixom.net>
>> You probably should map the SDC registers in the
>> platform startop code, and then have the various
>> platform drivers use that. Maybe even do an
>> abstraction ;-)
>
> Yep, it's a good idea to do and I'll look at it for 2.6.23 time frame.
Oh I'm sure you can get that done in time for .22 still ;-)
Segher
^ permalink raw reply
* Re: POSIX semaphores on ppc_6xx
From: Ben Warren @ 2007-04-27 0:10 UTC (permalink / raw)
To: Arnd Bergmann, linuxppc-embedded
In-Reply-To: <200704211733.13354.arnd@arndb.de>
Thanks Arnd,
--- Arnd Bergmann <arnd@arndb.de> wrote:
> On Friday 20 April 2007, Ben Warren wrote:
> > The cross-compiled glibc that is included in ELDK 4.0 doesn't seem to
> > have support for POSIX semaphores. I get the following runtime errors:
> >
> > sem_open: Function not implemented
> >
> > when trying to implement a named semaphore, and
> >
> > sem_init: Function not implemented
> >
> > when trying to implement an unnamed semaphore.
> >
> > Does anybody know if POSIX semaphores have been ported to ppc_6xx, and
> > if so, where I could find a binary copy?
>
> This normally works in every modern glibc. Maybe you were using an
> set of kernel headers that is too old. Make sure that you have
> up-to-date version of both kernel and glibc and that you use the
> kernel header files you get from 'make headers_install' in the kernel.
>
> Arnd <><
>
I haven't had a chance to try this out yet, but appreciate your tip!
regards,
Ben
^ permalink raw reply
* powerpc: Prepare for splitting up mmu.h by MMU type
From: David Gibson @ 2007-04-27 1:53 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
Currently asm-powerpc/mmu.h has definitions for the 64-bit hash based
MMU. If CONFIG_PPC64 is not set, it instead includes asm-ppc/mmu.h
which contains a particularly horrible mess of #ifdefs giving the
definitions for all the various 32-bit MMUs.
It would be nice to have the low level definitions for each MMU type
neatly in their own separate files. It would also be good to wean
arch/powerpc off dependence on the old asm-ppc/mmu.h.
This patch makes a start on such a cleanup bu moving the definitions
for the 64-bit hash MMU to their own file, asm-powerpc/mmu_hash64.h.
Definitions for the other MMUs still all come from asm-ppc/mmu.h,
however each MMU type can now be one-by-one moved over to their own
file, in the process cleaning them up stripping them of cruft no
longer necessary in arch/powerpc.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
Paulus, updated to resolve conflicts with recent additions to
powerpc.git. Please apply.
Index: working-2.6/include/asm-powerpc/mmu.h
===================================================================
--- working-2.6.orig/include/asm-powerpc/mmu.h 2007-04-26 10:36:37.000000000 +1000
+++ working-2.6/include/asm-powerpc/mmu.h 2007-04-26 11:34:00.000000000 +1000
@@ -2,408 +2,14 @@
#define _ASM_POWERPC_MMU_H_
#ifdef __KERNEL__
-#ifndef CONFIG_PPC64
-#include <asm-ppc/mmu.h>
+#ifdef CONFIG_PPC64
+/* 64-bit classic hash table MMU */
+# include <asm/mmu-hash64.h>
#else
-
-/*
- * PowerPC memory management structures
- *
- * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com>
- * PPC64 rework.
- *
- * 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 <asm/asm-compat.h>
-#include <asm/page.h>
-
-/*
- * Segment table
- */
-
-#define STE_ESID_V 0x80
-#define STE_ESID_KS 0x20
-#define STE_ESID_KP 0x10
-#define STE_ESID_N 0x08
-
-#define STE_VSID_SHIFT 12
-
-/* Location of cpu0's segment table */
-#define STAB0_PAGE 0x6
-#define STAB0_OFFSET (STAB0_PAGE << 12)
-#define STAB0_PHYS_ADDR (STAB0_OFFSET + PHYSICAL_START)
-
-#ifndef __ASSEMBLY__
-extern char initial_stab[];
-#endif /* ! __ASSEMBLY */
-
-/*
- * SLB
- */
-
-#define SLB_NUM_BOLTED 3
-#define SLB_CACHE_ENTRIES 8
-
-/* Bits in the SLB ESID word */
-#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */
-
-/* Bits in the SLB VSID word */
-#define SLB_VSID_SHIFT 12
-#define SLB_VSID_B ASM_CONST(0xc000000000000000)
-#define SLB_VSID_B_256M ASM_CONST(0x0000000000000000)
-#define SLB_VSID_B_1T ASM_CONST(0x4000000000000000)
-#define SLB_VSID_KS ASM_CONST(0x0000000000000800)
-#define SLB_VSID_KP ASM_CONST(0x0000000000000400)
-#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */
-#define SLB_VSID_L ASM_CONST(0x0000000000000100)
-#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */
-#define SLB_VSID_LP ASM_CONST(0x0000000000000030)
-#define SLB_VSID_LP_00 ASM_CONST(0x0000000000000000)
-#define SLB_VSID_LP_01 ASM_CONST(0x0000000000000010)
-#define SLB_VSID_LP_10 ASM_CONST(0x0000000000000020)
-#define SLB_VSID_LP_11 ASM_CONST(0x0000000000000030)
-#define SLB_VSID_LLP (SLB_VSID_L|SLB_VSID_LP)
-
-#define SLB_VSID_KERNEL (SLB_VSID_KP)
-#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C)
-
-#define SLBIE_C (0x08000000)
-
-/*
- * Hash table
- */
-
-#define HPTES_PER_GROUP 8
-
-#define HPTE_V_AVPN_SHIFT 7
-#define HPTE_V_AVPN ASM_CONST(0xffffffffffffff80)
-#define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
-#define HPTE_V_COMPARE(x,y) (!(((x) ^ (y)) & HPTE_V_AVPN))
-#define HPTE_V_BOLTED ASM_CONST(0x0000000000000010)
-#define HPTE_V_LOCK ASM_CONST(0x0000000000000008)
-#define HPTE_V_LARGE ASM_CONST(0x0000000000000004)
-#define HPTE_V_SECONDARY ASM_CONST(0x0000000000000002)
-#define HPTE_V_VALID ASM_CONST(0x0000000000000001)
-
-#define HPTE_R_PP0 ASM_CONST(0x8000000000000000)
-#define HPTE_R_TS ASM_CONST(0x4000000000000000)
-#define HPTE_R_RPN_SHIFT 12
-#define HPTE_R_RPN ASM_CONST(0x3ffffffffffff000)
-#define HPTE_R_FLAGS ASM_CONST(0x00000000000003ff)
-#define HPTE_R_PP ASM_CONST(0x0000000000000003)
-#define HPTE_R_N ASM_CONST(0x0000000000000004)
-#define HPTE_R_C ASM_CONST(0x0000000000000080)
-#define HPTE_R_R ASM_CONST(0x0000000000000100)
-
-/* Values for PP (assumes Ks=0, Kp=1) */
-/* pp0 will always be 0 for linux */
-#define PP_RWXX 0 /* Supervisor read/write, User none */
-#define PP_RWRX 1 /* Supervisor read/write, User read */
-#define PP_RWRW 2 /* Supervisor read/write, User read/write */
-#define PP_RXRX 3 /* Supervisor read, User read */
-
-#ifndef __ASSEMBLY__
-
-typedef struct {
- unsigned long v;
- unsigned long r;
-} hpte_t;
-
-extern hpte_t *htab_address;
-extern unsigned long htab_size_bytes;
-extern unsigned long htab_hash_mask;
-
-/*
- * Page size definition
- *
- * shift : is the "PAGE_SHIFT" value for that page size
- * sllp : is a bit mask with the value of SLB L || LP to be or'ed
- * directly to a slbmte "vsid" value
- * penc : is the HPTE encoding mask for the "LP" field:
- *
- */
-struct mmu_psize_def
-{
- unsigned int shift; /* number of bits */
- unsigned int penc; /* HPTE encoding */
- unsigned int tlbiel; /* tlbiel supported for that page size */
- unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */
- unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */
-};
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * The kernel use the constants below to index in the page sizes array.
- * The use of fixed constants for this purpose is better for performances
- * of the low level hash refill handlers.
- *
- * A non supported page size has a "shift" field set to 0
- *
- * Any new page size being implemented can get a new entry in here. Whether
- * the kernel will use it or not is a different matter though. The actual page
- * size used by hugetlbfs is not defined here and may be made variable
- */
-
-#define MMU_PAGE_4K 0 /* 4K */
-#define MMU_PAGE_64K 1 /* 64K */
-#define MMU_PAGE_64K_AP 2 /* 64K Admixed (in a 4K segment) */
-#define MMU_PAGE_1M 3 /* 1M */
-#define MMU_PAGE_16M 4 /* 16M */
-#define MMU_PAGE_16G 5 /* 16G */
-#define MMU_PAGE_COUNT 6
-
-#ifndef __ASSEMBLY__
-
-/*
- * The current system page sizes
- */
-extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
-extern int mmu_linear_psize;
-extern int mmu_virtual_psize;
-extern int mmu_vmalloc_psize;
-extern int mmu_io_psize;
-
-/*
- * If the processor supports 64k normal pages but not 64k cache
- * inhibited pages, we have to be prepared to switch processes
- * to use 4k pages when they create cache-inhibited mappings.
- * If this is the case, mmu_ci_restrictions will be set to 1.
- */
-extern int mmu_ci_restrictions;
-
-#ifdef CONFIG_HUGETLB_PAGE
-/*
- * The page size index of the huge pages for use by hugetlbfs
- */
-extern int mmu_huge_psize;
-
-#endif /* CONFIG_HUGETLB_PAGE */
-
-/*
- * This function sets the AVPN and L fields of the HPTE appropriately
- * for the page size
- */
-static inline unsigned long hpte_encode_v(unsigned long va, int psize)
-{
- unsigned long v =
- v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
- v <<= HPTE_V_AVPN_SHIFT;
- if (psize != MMU_PAGE_4K)
- v |= HPTE_V_LARGE;
- return v;
-}
-
-/*
- * This function sets the ARPN, and LP fields of the HPTE appropriately
- * for the page size. We assume the pa is already "clean" that is properly
- * aligned for the requested page size
- */
-static inline unsigned long hpte_encode_r(unsigned long pa, int psize)
-{
- unsigned long r;
-
- /* A 4K page needs no special encoding */
- if (psize == MMU_PAGE_4K)
- return pa & HPTE_R_RPN;
- else {
- unsigned int penc = mmu_psize_defs[psize].penc;
- unsigned int shift = mmu_psize_defs[psize].shift;
- return (pa & ~((1ul << shift) - 1)) | (penc << 12);
- }
- return r;
-}
-
-/*
- * This hashes a virtual address for a 256Mb segment only for now
- */
-
-static inline unsigned long hpt_hash(unsigned long va, unsigned int shift)
-{
- return ((va >> 28) & 0x7fffffffffUL) ^ ((va & 0x0fffffffUL) >> shift);
-}
-
-extern int __hash_page_4K(unsigned long ea, unsigned long access,
- unsigned long vsid, pte_t *ptep, unsigned long trap,
- unsigned int local);
-extern int __hash_page_64K(unsigned long ea, unsigned long access,
- unsigned long vsid, pte_t *ptep, unsigned long trap,
- unsigned int local);
-struct mm_struct;
-extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap);
-extern int hash_huge_page(struct mm_struct *mm, unsigned long access,
- unsigned long ea, unsigned long vsid, int local,
- unsigned long trap);
-
-extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
- unsigned long pstart, unsigned long mode,
- int psize);
-
-extern void htab_initialize(void);
-extern void htab_initialize_secondary(void);
-extern void hpte_init_native(void);
-extern void hpte_init_lpar(void);
-extern void hpte_init_iSeries(void);
-extern void hpte_init_beat(void);
-
-extern void stabs_alloc(void);
-extern void slb_initialize(void);
-extern void slb_flush_and_rebolt(void);
-extern void stab_initialize(unsigned long stab);
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * VSID allocation
- *
- * We first generate a 36-bit "proto-VSID". For kernel addresses this
- * is equal to the ESID, for user addresses it is:
- * (context << 15) | (esid & 0x7fff)
- *
- * The two forms are distinguishable because the top bit is 0 for user
- * addresses, whereas the top two bits are 1 for kernel addresses.
- * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
- * now.
- *
- * The proto-VSIDs are then scrambled into real VSIDs with the
- * multiplicative hash:
- *
- * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
- * where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
- * VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
- *
- * This scramble is only well defined for proto-VSIDs below
- * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
- * reserved. VSID_MULTIPLIER is prime, so in particular it is
- * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
- * Because the modulus is 2^n-1 we can compute it efficiently without
- * a divide or extra multiply (see below).
- *
- * This scheme has several advantages over older methods:
- *
- * - We have VSIDs allocated for every kernel address
- * (i.e. everything above 0xC000000000000000), except the very top
- * segment, which simplifies several things.
- *
- * - We allow for 15 significant bits of ESID and 20 bits of
- * context for user addresses. i.e. 8T (43 bits) of address space for
- * up to 1M contexts (although the page table structure and context
- * allocation will need changes to take advantage of this).
- *
- * - The scramble function gives robust scattering in the hash
- * table (at least based on some initial results). The previous
- * method was more susceptible to pathological cases giving excessive
- * hash collisions.
- */
-/*
- * WARNING - If you change these you must make sure the asm
- * implementations in slb_allocate (slb_low.S), do_stab_bolted
- * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
- *
- * You'll also need to change the precomputed VSID values in head.S
- * which are used by the iSeries firmware.
- */
-
-#define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */
-#define VSID_BITS 36
-#define VSID_MODULUS ((1UL<<VSID_BITS)-1)
-
-#define CONTEXT_BITS 19
-#define USER_ESID_BITS 16
-
-#define USER_VSID_RANGE (1UL << (USER_ESID_BITS + SID_SHIFT))
-
-/*
- * This macro generates asm code to compute the VSID scramble
- * function. Used in slb_allocate() and do_stab_bolted. The function
- * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS
- *
- * rt = register continaing the proto-VSID and into which the
- * VSID will be stored
- * rx = scratch register (clobbered)
- *
- * - rt and rx must be different registers
- * - The answer will end up in the low 36 bits of rt. The higher
- * bits may contain other garbage, so you may need to mask the
- * result.
- */
-#define ASM_VSID_SCRAMBLE(rt, rx) \
- lis rx,VSID_MULTIPLIER@h; \
- ori rx,rx,VSID_MULTIPLIER@l; \
- mulld rt,rt,rx; /* rt = rt * MULTIPLIER */ \
- \
- srdi rx,rt,VSID_BITS; \
- clrldi rt,rt,(64-VSID_BITS); \
- add rt,rt,rx; /* add high and low bits */ \
- /* Now, r3 == VSID (mod 2^36-1), and lies between 0 and \
- * 2^36-1+2^28-1. That in particular means that if r3 >= \
- * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \
- * the bit clear, r3 already has the answer we want, if it \
- * doesn't, the answer is the low 36 bits of r3+1. So in all \
- * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\
- addi rx,rt,1; \
- srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \
- add rt,rt,rx
-
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long mm_context_id_t;
-
-typedef struct {
- mm_context_id_t id;
- u16 user_psize; /* page size index */
- u16 sllp; /* SLB entry page size encoding */
-#ifdef CONFIG_HUGETLB_PAGE
- u16 low_htlb_areas, high_htlb_areas;
+/* 32-bit. FIXME: split up the 32-bit MMU types, and revise for
+ * arch/powerpc */
+# include <asm-ppc/mmu.h>
#endif
- unsigned long vdso_base;
-} mm_context_t;
-
-
-static inline unsigned long vsid_scramble(unsigned long protovsid)
-{
-#if 0
- /* The code below is equivalent to this function for arguments
- * < 2^VSID_BITS, which is all this should ever be called
- * with. However gcc is not clever enough to compute the
- * modulus (2^n-1) without a second multiply. */
- return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS);
-#else /* 1 */
- unsigned long x;
-
- x = protovsid * VSID_MULTIPLIER;
- x = (x >> VSID_BITS) + (x & VSID_MODULUS);
- return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS;
-#endif /* 1 */
-}
-
-/* This is only valid for addresses >= KERNELBASE */
-static inline unsigned long get_kernel_vsid(unsigned long ea)
-{
- return vsid_scramble(ea >> SID_SHIFT);
-}
-
-/* This is only valid for user addresses (which are below 2^41) */
-static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
-{
- return vsid_scramble((context << USER_ESID_BITS)
- | (ea >> SID_SHIFT));
-}
-
-#define VSID_SCRAMBLE(pvsid) (((pvsid) * VSID_MULTIPLIER) % VSID_MODULUS)
-#define KERNEL_VSID(ea) VSID_SCRAMBLE(GET_ESID(ea))
-
-/* Physical address used by some IO functions */
-typedef unsigned long phys_addr_t;
-
-
-#endif /* __ASSEMBLY */
-#endif /* CONFIG_PPC64 */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MMU_H_ */
Index: working-2.6/include/asm-powerpc/mmu-hash64.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ working-2.6/include/asm-powerpc/mmu-hash64.h 2007-04-26 11:33:11.000000000 +1000
@@ -0,0 +1,400 @@
+#ifndef _ASM_POWERPC_MMU_HASH64_H_
+#define _ASM_POWERPC_MMU_HASH64_H_
+/*
+ * PowerPC64 memory management structures
+ *
+ * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com>
+ * PPC64 rework.
+ *
+ * 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 <asm/asm-compat.h>
+#include <asm/page.h>
+
+/*
+ * Segment table
+ */
+
+#define STE_ESID_V 0x80
+#define STE_ESID_KS 0x20
+#define STE_ESID_KP 0x10
+#define STE_ESID_N 0x08
+
+#define STE_VSID_SHIFT 12
+
+/* Location of cpu0's segment table */
+#define STAB0_PAGE 0x6
+#define STAB0_OFFSET (STAB0_PAGE << 12)
+#define STAB0_PHYS_ADDR (STAB0_OFFSET + PHYSICAL_START)
+
+#ifndef __ASSEMBLY__
+extern char initial_stab[];
+#endif /* ! __ASSEMBLY */
+
+/*
+ * SLB
+ */
+
+#define SLB_NUM_BOLTED 3
+#define SLB_CACHE_ENTRIES 8
+
+/* Bits in the SLB ESID word */
+#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */
+
+/* Bits in the SLB VSID word */
+#define SLB_VSID_SHIFT 12
+#define SLB_VSID_B ASM_CONST(0xc000000000000000)
+#define SLB_VSID_B_256M ASM_CONST(0x0000000000000000)
+#define SLB_VSID_B_1T ASM_CONST(0x4000000000000000)
+#define SLB_VSID_KS ASM_CONST(0x0000000000000800)
+#define SLB_VSID_KP ASM_CONST(0x0000000000000400)
+#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */
+#define SLB_VSID_L ASM_CONST(0x0000000000000100)
+#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */
+#define SLB_VSID_LP ASM_CONST(0x0000000000000030)
+#define SLB_VSID_LP_00 ASM_CONST(0x0000000000000000)
+#define SLB_VSID_LP_01 ASM_CONST(0x0000000000000010)
+#define SLB_VSID_LP_10 ASM_CONST(0x0000000000000020)
+#define SLB_VSID_LP_11 ASM_CONST(0x0000000000000030)
+#define SLB_VSID_LLP (SLB_VSID_L|SLB_VSID_LP)
+
+#define SLB_VSID_KERNEL (SLB_VSID_KP)
+#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C)
+
+#define SLBIE_C (0x08000000)
+
+/*
+ * Hash table
+ */
+
+#define HPTES_PER_GROUP 8
+
+#define HPTE_V_AVPN_SHIFT 7
+#define HPTE_V_AVPN ASM_CONST(0xffffffffffffff80)
+#define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
+#define HPTE_V_COMPARE(x,y) (!(((x) ^ (y)) & HPTE_V_AVPN))
+#define HPTE_V_BOLTED ASM_CONST(0x0000000000000010)
+#define HPTE_V_LOCK ASM_CONST(0x0000000000000008)
+#define HPTE_V_LARGE ASM_CONST(0x0000000000000004)
+#define HPTE_V_SECONDARY ASM_CONST(0x0000000000000002)
+#define HPTE_V_VALID ASM_CONST(0x0000000000000001)
+
+#define HPTE_R_PP0 ASM_CONST(0x8000000000000000)
+#define HPTE_R_TS ASM_CONST(0x4000000000000000)
+#define HPTE_R_RPN_SHIFT 12
+#define HPTE_R_RPN ASM_CONST(0x3ffffffffffff000)
+#define HPTE_R_FLAGS ASM_CONST(0x00000000000003ff)
+#define HPTE_R_PP ASM_CONST(0x0000000000000003)
+#define HPTE_R_N ASM_CONST(0x0000000000000004)
+#define HPTE_R_C ASM_CONST(0x0000000000000080)
+#define HPTE_R_R ASM_CONST(0x0000000000000100)
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+/* pp0 will always be 0 for linux */
+#define PP_RWXX 0 /* Supervisor read/write, User none */
+#define PP_RWRX 1 /* Supervisor read/write, User read */
+#define PP_RWRW 2 /* Supervisor read/write, User read/write */
+#define PP_RXRX 3 /* Supervisor read, User read */
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+ unsigned long v;
+ unsigned long r;
+} hpte_t;
+
+extern hpte_t *htab_address;
+extern unsigned long htab_size_bytes;
+extern unsigned long htab_hash_mask;
+
+/*
+ * Page size definition
+ *
+ * shift : is the "PAGE_SHIFT" value for that page size
+ * sllp : is a bit mask with the value of SLB L || LP to be or'ed
+ * directly to a slbmte "vsid" value
+ * penc : is the HPTE encoding mask for the "LP" field:
+ *
+ */
+struct mmu_psize_def
+{
+ unsigned int shift; /* number of bits */
+ unsigned int penc; /* HPTE encoding */
+ unsigned int tlbiel; /* tlbiel supported for that page size */
+ unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */
+ unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */
+};
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * The kernel use the constants below to index in the page sizes array.
+ * The use of fixed constants for this purpose is better for performances
+ * of the low level hash refill handlers.
+ *
+ * A non supported page size has a "shift" field set to 0
+ *
+ * Any new page size being implemented can get a new entry in here. Whether
+ * the kernel will use it or not is a different matter though. The actual page
+ * size used by hugetlbfs is not defined here and may be made variable
+ */
+
+#define MMU_PAGE_4K 0 /* 4K */
+#define MMU_PAGE_64K 1 /* 64K */
+#define MMU_PAGE_64K_AP 2 /* 64K Admixed (in a 4K segment) */
+#define MMU_PAGE_1M 3 /* 1M */
+#define MMU_PAGE_16M 4 /* 16M */
+#define MMU_PAGE_16G 5 /* 16G */
+#define MMU_PAGE_COUNT 6
+
+#ifndef __ASSEMBLY__
+
+/*
+ * The current system page sizes
+ */
+extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
+extern int mmu_linear_psize;
+extern int mmu_virtual_psize;
+extern int mmu_vmalloc_psize;
+extern int mmu_io_psize;
+
+/*
+ * If the processor supports 64k normal pages but not 64k cache
+ * inhibited pages, we have to be prepared to switch processes
+ * to use 4k pages when they create cache-inhibited mappings.
+ * If this is the case, mmu_ci_restrictions will be set to 1.
+ */
+extern int mmu_ci_restrictions;
+
+#ifdef CONFIG_HUGETLB_PAGE
+/*
+ * The page size index of the huge pages for use by hugetlbfs
+ */
+extern int mmu_huge_psize;
+
+#endif /* CONFIG_HUGETLB_PAGE */
+
+/*
+ * This function sets the AVPN and L fields of the HPTE appropriately
+ * for the page size
+ */
+static inline unsigned long hpte_encode_v(unsigned long va, int psize)
+{
+ unsigned long v =
+ v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
+ v <<= HPTE_V_AVPN_SHIFT;
+ if (psize != MMU_PAGE_4K)
+ v |= HPTE_V_LARGE;
+ return v;
+}
+
+/*
+ * This function sets the ARPN, and LP fields of the HPTE appropriately
+ * for the page size. We assume the pa is already "clean" that is properly
+ * aligned for the requested page size
+ */
+static inline unsigned long hpte_encode_r(unsigned long pa, int psize)
+{
+ unsigned long r;
+
+ /* A 4K page needs no special encoding */
+ if (psize == MMU_PAGE_4K)
+ return pa & HPTE_R_RPN;
+ else {
+ unsigned int penc = mmu_psize_defs[psize].penc;
+ unsigned int shift = mmu_psize_defs[psize].shift;
+ return (pa & ~((1ul << shift) - 1)) | (penc << 12);
+ }
+ return r;
+}
+
+/*
+ * This hashes a virtual address for a 256Mb segment only for now
+ */
+
+static inline unsigned long hpt_hash(unsigned long va, unsigned int shift)
+{
+ return ((va >> 28) & 0x7fffffffffUL) ^ ((va & 0x0fffffffUL) >> shift);
+}
+
+extern int __hash_page_4K(unsigned long ea, unsigned long access,
+ unsigned long vsid, pte_t *ptep, unsigned long trap,
+ unsigned int local);
+extern int __hash_page_64K(unsigned long ea, unsigned long access,
+ unsigned long vsid, pte_t *ptep, unsigned long trap,
+ unsigned int local);
+struct mm_struct;
+extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap);
+extern int hash_huge_page(struct mm_struct *mm, unsigned long access,
+ unsigned long ea, unsigned long vsid, int local,
+ unsigned long trap);
+
+extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
+ unsigned long pstart, unsigned long mode,
+ int psize);
+
+extern void htab_initialize(void);
+extern void htab_initialize_secondary(void);
+extern void hpte_init_native(void);
+extern void hpte_init_lpar(void);
+extern void hpte_init_iSeries(void);
+extern void hpte_init_beat(void);
+
+extern void stabs_alloc(void);
+extern void slb_initialize(void);
+extern void slb_flush_and_rebolt(void);
+extern void stab_initialize(unsigned long stab);
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * VSID allocation
+ *
+ * We first generate a 36-bit "proto-VSID". For kernel addresses this
+ * is equal to the ESID, for user addresses it is:
+ * (context << 15) | (esid & 0x7fff)
+ *
+ * The two forms are distinguishable because the top bit is 0 for user
+ * addresses, whereas the top two bits are 1 for kernel addresses.
+ * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
+ * now.
+ *
+ * The proto-VSIDs are then scrambled into real VSIDs with the
+ * multiplicative hash:
+ *
+ * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
+ * where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
+ * VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
+ *
+ * This scramble is only well defined for proto-VSIDs below
+ * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
+ * reserved. VSID_MULTIPLIER is prime, so in particular it is
+ * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
+ * Because the modulus is 2^n-1 we can compute it efficiently without
+ * a divide or extra multiply (see below).
+ *
+ * This scheme has several advantages over older methods:
+ *
+ * - We have VSIDs allocated for every kernel address
+ * (i.e. everything above 0xC000000000000000), except the very top
+ * segment, which simplifies several things.
+ *
+ * - We allow for 15 significant bits of ESID and 20 bits of
+ * context for user addresses. i.e. 8T (43 bits) of address space for
+ * up to 1M contexts (although the page table structure and context
+ * allocation will need changes to take advantage of this).
+ *
+ * - The scramble function gives robust scattering in the hash
+ * table (at least based on some initial results). The previous
+ * method was more susceptible to pathological cases giving excessive
+ * hash collisions.
+ */
+/*
+ * WARNING - If you change these you must make sure the asm
+ * implementations in slb_allocate (slb_low.S), do_stab_bolted
+ * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
+ *
+ * You'll also need to change the precomputed VSID values in head.S
+ * which are used by the iSeries firmware.
+ */
+
+#define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */
+#define VSID_BITS 36
+#define VSID_MODULUS ((1UL<<VSID_BITS)-1)
+
+#define CONTEXT_BITS 19
+#define USER_ESID_BITS 16
+
+#define USER_VSID_RANGE (1UL << (USER_ESID_BITS + SID_SHIFT))
+
+/*
+ * This macro generates asm code to compute the VSID scramble
+ * function. Used in slb_allocate() and do_stab_bolted. The function
+ * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS
+ *
+ * rt = register continaing the proto-VSID and into which the
+ * VSID will be stored
+ * rx = scratch register (clobbered)
+ *
+ * - rt and rx must be different registers
+ * - The answer will end up in the low 36 bits of rt. The higher
+ * bits may contain other garbage, so you may need to mask the
+ * result.
+ */
+#define ASM_VSID_SCRAMBLE(rt, rx) \
+ lis rx,VSID_MULTIPLIER@h; \
+ ori rx,rx,VSID_MULTIPLIER@l; \
+ mulld rt,rt,rx; /* rt = rt * MULTIPLIER */ \
+ \
+ srdi rx,rt,VSID_BITS; \
+ clrldi rt,rt,(64-VSID_BITS); \
+ add rt,rt,rx; /* add high and low bits */ \
+ /* Now, r3 == VSID (mod 2^36-1), and lies between 0 and \
+ * 2^36-1+2^28-1. That in particular means that if r3 >= \
+ * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \
+ * the bit clear, r3 already has the answer we want, if it \
+ * doesn't, the answer is the low 36 bits of r3+1. So in all \
+ * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\
+ addi rx,rt,1; \
+ srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \
+ add rt,rt,rx
+
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long mm_context_id_t;
+
+typedef struct {
+ mm_context_id_t id;
+ u16 user_psize; /* page size index */
+ u16 sllp; /* SLB entry page size encoding */
+#ifdef CONFIG_HUGETLB_PAGE
+ u16 low_htlb_areas, high_htlb_areas;
+#endif
+ unsigned long vdso_base;
+} mm_context_t;
+
+
+static inline unsigned long vsid_scramble(unsigned long protovsid)
+{
+#if 0
+ /* The code below is equivalent to this function for arguments
+ * < 2^VSID_BITS, which is all this should ever be called
+ * with. However gcc is not clever enough to compute the
+ * modulus (2^n-1) without a second multiply. */
+ return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS);
+#else /* 1 */
+ unsigned long x;
+
+ x = protovsid * VSID_MULTIPLIER;
+ x = (x >> VSID_BITS) + (x & VSID_MODULUS);
+ return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS;
+#endif /* 1 */
+}
+
+/* This is only valid for addresses >= KERNELBASE */
+static inline unsigned long get_kernel_vsid(unsigned long ea)
+{
+ return vsid_scramble(ea >> SID_SHIFT);
+}
+
+/* This is only valid for user addresses (which are below 2^41) */
+static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
+{
+ return vsid_scramble((context << USER_ESID_BITS)
+ | (ea >> SID_SHIFT));
+}
+
+#define VSID_SCRAMBLE(pvsid) (((pvsid) * VSID_MULTIPLIER) % VSID_MODULUS)
+#define KERNEL_VSID(ea) VSID_SCRAMBLE(GET_ESID(ea))
+
+/* Physical address used by some IO functions */
+typedef unsigned long phys_addr_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_HASH64_H_ */
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Small cleanups to the cuboot bootwrapper code
From: David Gibson @ 2007-04-27 2:01 UTC (permalink / raw)
To: Paul Mackerras, Scott Wood; +Cc: linuxppc-dev
This patch makes a few small cleanups to the cuboot code.
- It removes the double layered selection of images, via
cuboot-plat-y, instead having the cuboot platforms directly select a
suitable image-y (this changes the name of the final cuboot image from
plain cuImage to cuImage.<platform>).
- Factors out some code in the wrapper that's potentially
useful to platforms other than uboot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
arch/powerpc/boot/Makefile | 13 +++++--------
arch/powerpc/boot/wrapper | 28 +++++++++++++---------------
2 files changed, 18 insertions(+), 23 deletions(-)
Scott, I don't have the boards to test this patch with, though I think
it should be ok. If it seems ok to you, please ack, then Paul can
apply.
Index: working-2.6/arch/powerpc/boot/Makefile
===================================================================
--- working-2.6.orig/arch/powerpc/boot/Makefile 2007-04-27 11:48:56.000000000 +1000
+++ working-2.6/arch/powerpc/boot/Makefile 2007-04-27 11:57:41.000000000 +1000
@@ -129,7 +129,8 @@ image-$(CONFIG_PPC_CELLEB) += zImage.ps
image-$(CONFIG_PPC_CHRP) += zImage.chrp
image-$(CONFIG_PPC_EFIKA) += zImage.chrp
image-$(CONFIG_PPC_PMAC) += zImage.pmac
-image-$(CONFIG_DEFAULT_UIMAGE) += uImage cuImage
+image-$(CONFIG_PPC_83xx) += cuImage.83xx
+image-$(CONFIG_DEFAULT_UIMAGE) += uImage
# For 32-bit powermacs, build the COFF and miboot images
# as well as the ELF images.
@@ -162,14 +163,11 @@ $(obj)/zImage.initrd.ps3: vmlinux
$(obj)/uImage: vmlinux $(wrapperbits)
$(call if_changed,wrap,uboot)
-cuboot-plat-$(CONFIG_83xx) += 83xx
-cuboot-plat-y += unknown-platform
-
dts = $(if $(shell echo $(CONFIG_) | grep '^/'),\
,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE)
-$(obj)/cuImage: vmlinux $(wrapperbits)
- $(call if_changed,wrap,cuboot-$(word 1,$(cuboot-plat-y)),$(dts))
+$(obj)/cuImage.%: vmlinux $(wrapperbits)
+ $(call if_changed,wrap,cuboot-$*,$(dts))
$(obj)/zImage: $(addprefix $(obj)/, $(image-y))
@rm -f $@; ln $< $@
@@ -180,8 +178,7 @@ install: $(CONFIGURE) $(image-y)
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
# anything not in $(targets)
-clean-files += $(image-) $(initrd-) zImage zImage.initrd \
- cuImage.elf cuImage.bin.gz
+clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.*
# clean up files cached by wrapper
clean-kernel := vmlinux.strip vmlinux.bin
Index: working-2.6/arch/powerpc/boot/wrapper
===================================================================
--- working-2.6.orig/arch/powerpc/boot/wrapper 2007-04-26 13:57:24.000000000 +1000
+++ working-2.6/arch/powerpc/boot/wrapper 2007-04-27 11:57:41.000000000 +1000
@@ -163,20 +163,19 @@ fi
vmz="$vmz$gzip"
-case "$platform" in
-uboot|cuboot*)
- version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \
- cut -d' ' -f3`
- if [ -n "$version" ]; then
- version="-n Linux-$version"
- fi
-esac
+# Extract kernel version information, some platforms want to include
+# it in the image header
+version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \
+ cut -d' ' -f3`
+if [ -n "$version" ]; then
+ uboot_version="-n Linux-$version"
+fi
case "$platform" in
uboot)
rm -f "$ofile"
mkimage -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \
- $version -d "$vmz" "$ofile"
+ $uboot_version -d "$vmz" "$ofile"
if [ -z "$cacheit" ]; then
rm -f "$vmz"
fi
@@ -212,25 +211,24 @@ if [ "$platform" != "miboot" ]; then
rm $tmp
fi
+# Some platforms need the zImage's entry point and base address
+base=0x`${CROSS}nm "$ofile" | grep ' _start$' | cut -d' ' -f1`
+entry=`${CROSS}objdump -f "$ofile" | grep '^start address ' | cut -d' ' -f3`
+
# post-processing needed for some platforms
case "$platform" in
pseries|chrp)
$object/addnote "$ofile"
;;
pmaccoff)
- entry=`objdump -f "$ofile" | grep '^start address ' | \
- cut -d' ' -f3`
${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
$object/hack-coff "$ofile"
;;
cuboot*)
- base=`${CROSS}nm "$ofile" | grep ' _start$' | cut -d' ' -f1`
- entry=`${CROSS}objdump -f "$ofile" | grep '^start address ' | \
- cut -d' ' -f3`
mv "$ofile" "$ofile".elf
${CROSS}objcopy -O binary "$ofile".elf "$ofile".bin
gzip -f -9 "$ofile".bin
mkimage -A ppc -O linux -T kernel -C gzip -a "$base" -e "$entry" \
- $version -d "$ofile".bin.gz "$ofile"
+ $uboot_version -d "$ofile".bin.gz "$ofile"
;;
esac
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
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