* ramdisk - machine check exception
From: Siva Prasad @ 2007-04-18 4:15 UTC (permalink / raw)
To: linuxppc-dev, linuxppc-embedded
Hi,
I am getting Machine Check exception due to the following scenario.
I am trying to use ramdisk for the file system with physical memory from
0x40000000 (instead of the regular 0x00000000). Of course this starts
the run_init_process with ramdisk_execute_command ("/init"). This
eventually calls load_elf_binary -> padzero -> __clear_user(addr, size).
This addr value for __clear_user came in as 0x101b2f98, accessing which
I got the exception.
Now my question is, why am I getting 0x101b2f98. I tried to do some
research and found that this is coming from elf_phdata->p_vaddr
(0x10000000) from routine load_elf_binary. This just kernel_read's from
file pointer of "/init", which I don't completely understand. Shouldn't
this value be greater than 0xc0000000. Where is this value coming from?
Also I don't understand how this would work even in regular memory
systems starting at 0x00000000, as MMU is enabled and mapped to
0xc0000000.
Appreciate any help.
Thanks
Siva
^ permalink raw reply
* Re: [PATCH: dtc] Improve -S handling
From: David Gibson @ 2007-04-18 3:05 UTC (permalink / raw)
To: Jerry Van Baren; +Cc: linuxppc-dev, jdl
In-Reply-To: <20070418020535.GA16224@dellserver.lan>
On Tue, Apr 17, 2007 at 10:05:35PM -0400, Jerry Van Baren wrote:
> If the user requests extra space, pad out the blob (previously the unused
> data was undefined).
>
> Signed-off-by: Gerald Van Baren <vanbaren@cideas.com>
> ---
>
> Hi Jon, David, Milton,
>
> This improves the -S option to pad out the blob with zeros when the user
> asks for extra space.
Comment below
> diff --git a/flattree.c b/flattree.c
> index 151d16e..d2ee0dc 100644
> --- a/flattree.c
> +++ b/flattree.c
> @@ -310,6 +310,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
>
> return d;
> }
> +
> static void make_bph(struct boot_param_header *bph,
> struct version_info *vi,
> int reservesize, int dtsize, int strsize,
> @@ -358,12 +359,15 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
> {
> struct version_info *vi = NULL;
> int i;
> + int size;
> struct data dtbuf = empty_data;
> struct data strbuf = empty_data;
> struct data reservebuf;
> struct boot_param_header bph;
> struct reserve_entry termre = {.address = 0, .size = 0};
>
> + size = 0;
> +
> for (i = 0; i < ARRAY_SIZE(version_table); i++) {
> if (version_table[i].version == version)
> vi = &version_table[i];
> @@ -384,10 +388,13 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
> boot_cpuid_phys);
>
> fwrite(&bph, vi->hdr_size, 1, f);
> + size += vi->hdr_size;
>
> /* Align the reserve map to an 8 byte boundary */
> - for (i = vi->hdr_size; i < be32_to_cpu(bph.off_mem_rsvmap); i++)
> + for (i = vi->hdr_size; i < be32_to_cpu(bph.off_mem_rsvmap); i++) {
> fputc(0, f);
> + size += 1;
> + }
>
> /*
> * Reserve map entries.
> @@ -396,9 +403,27 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
> */
> fwrite(reservebuf.val, reservebuf.len, 1, f);
> fwrite(&termre, sizeof(termre), 1, f);
> + size += reservebuf.len + sizeof(termre);
>
> fwrite(dtbuf.val, dtbuf.len, 1, f);
> fwrite(strbuf.val, strbuf.len, 1, f);
> + size += dtbuf.len + strbuf.len;
> +
> + /*
> + * If the user asked for more space than is used, pad it out.
> + */
> + if (minsize > 0) {
> + int padlen = minsize - size;
> +
> + if (padlen > 0) {
> + char *zeroes = calloc(padlen, 1);
> +
> + if (zeroes != NULL) {
> + fwrite(zeroes, padlen, 1, f);
> + free(zeroes);
> + }
> + }
> + }
Hrm, rather than all this explicit calloc() mangling, I'd prefer we
use our existing struct data stuff. Use data_append_zeroes() on
empty_data to generate your buffer of padding.
> if (ferror(f))
> die("Error writing device tree blob: %s\n", strerror(errno));
> @@ -504,6 +529,14 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys)
>
> emit_label(f, symprefix, "blob_end");
>
> + /*
> + * If the user asked for more space than is used, pad it out.
> + */
> + if (minsize > 0) {
> + fprintf(f, "\t.space\t%d - (%s_blob_end - %s_blob_start), 0\n",
> + minsize, symprefix, symprefix);
> + }
> +
> data_free(strbuf);
> }
>
--
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
* [PATCH: dtc] Improve -S handling
From: Jerry Van Baren @ 2007-04-18 2:05 UTC (permalink / raw)
To: linuxppc-dev, jdl
If the user requests extra space, pad out the blob (previously the unused
data was undefined).
Signed-off-by: Gerald Van Baren <vanbaren@cideas.com>
---
Hi Jon, David, Milton,
This improves the -S option to pad out the blob with zeros when the user
asks for extra space.
Best regards,
gvb
flattree.c | 35 ++++++++++++++++++++++++++++++++++-
1 files changed, 34 insertions(+), 1 deletions(-)
diff --git a/flattree.c b/flattree.c
index 151d16e..d2ee0dc 100644
--- a/flattree.c
+++ b/flattree.c
@@ -310,6 +310,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
return d;
}
+
static void make_bph(struct boot_param_header *bph,
struct version_info *vi,
int reservesize, int dtsize, int strsize,
@@ -358,12 +359,15 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
{
struct version_info *vi = NULL;
int i;
+ int size;
struct data dtbuf = empty_data;
struct data strbuf = empty_data;
struct data reservebuf;
struct boot_param_header bph;
struct reserve_entry termre = {.address = 0, .size = 0};
+ size = 0;
+
for (i = 0; i < ARRAY_SIZE(version_table); i++) {
if (version_table[i].version == version)
vi = &version_table[i];
@@ -384,10 +388,13 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
boot_cpuid_phys);
fwrite(&bph, vi->hdr_size, 1, f);
+ size += vi->hdr_size;
/* Align the reserve map to an 8 byte boundary */
- for (i = vi->hdr_size; i < be32_to_cpu(bph.off_mem_rsvmap); i++)
+ for (i = vi->hdr_size; i < be32_to_cpu(bph.off_mem_rsvmap); i++) {
fputc(0, f);
+ size += 1;
+ }
/*
* Reserve map entries.
@@ -396,9 +403,27 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
*/
fwrite(reservebuf.val, reservebuf.len, 1, f);
fwrite(&termre, sizeof(termre), 1, f);
+ size += reservebuf.len + sizeof(termre);
fwrite(dtbuf.val, dtbuf.len, 1, f);
fwrite(strbuf.val, strbuf.len, 1, f);
+ size += dtbuf.len + strbuf.len;
+
+ /*
+ * If the user asked for more space than is used, pad it out.
+ */
+ if (minsize > 0) {
+ int padlen = minsize - size;
+
+ if (padlen > 0) {
+ char *zeroes = calloc(padlen, 1);
+
+ if (zeroes != NULL) {
+ fwrite(zeroes, padlen, 1, f);
+ free(zeroes);
+ }
+ }
+ }
if (ferror(f))
die("Error writing device tree blob: %s\n", strerror(errno));
@@ -504,6 +529,14 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys)
emit_label(f, symprefix, "blob_end");
+ /*
+ * If the user asked for more space than is used, pad it out.
+ */
+ if (minsize > 0) {
+ fprintf(f, "\t.space\t%d - (%s_blob_end - %s_blob_start), 0\n",
+ minsize, symprefix, symprefix);
+ }
+
data_free(strbuf);
}
--
1.4.4.4
^ permalink raw reply related
* [PATCH] Initialise spinlock in the DEBUG_PAGEALLOC code
From: Michael Ellerman @ 2007-04-18 1:50 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
Fixes:
BUG: spinlock bad magic on CPU#0, swapper/0
lock: c00000000064ec30, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0
Call Trace:
[c00000000062b980] [c00000000000f920] .show_stack+0x6c/0x1a0 (unreliable)
[c00000000062ba20] [c0000000001c2b40] .spin_bug+0xb0/0xd4
[c00000000062bab0] [c0000000001c2ed0] ._raw_spin_lock+0x44/0x184
[c00000000062bb50] [c0000000003a42b4] ._spin_lock+0x10/0x24
[c00000000062bbd0] [c00000000002b4dc] .kernel_map_pages+0x198/0x278
[c00000000062bc90] [c000000000079720] .free_hot_cold_page+0x124/0x418
[c00000000062bd70] [c000000000530278] .free_all_bootmem_core+0x14c/0x224
[c00000000062be50] [c00000000052a178] .mem_init+0x68/0x170
[c00000000062bee0] [c00000000051d874] .start_kernel+0x2a0/0x37c
[c00000000062bf90] [c0000000000084c8] .start_here_common+0x54/0x8c
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/mm/hash_utils_64.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: powerpc/arch/powerpc/mm/hash_utils_64.c
===================================================================
--- powerpc.orig/arch/powerpc/mm/hash_utils_64.c
+++ powerpc/arch/powerpc/mm/hash_utils_64.c
@@ -103,7 +103,7 @@ int mmu_ci_restrictions;
#ifdef CONFIG_DEBUG_PAGEALLOC
static u8 *linear_map_hash_slots;
static unsigned long linear_map_hash_count;
-static spinlock_t linear_map_hash_lock;
+static DEFINE_SPINLOCK(linear_map_hash_lock);
#endif /* CONFIG_DEBUG_PAGEALLOC */
/* There are definitions of page sizes arrays to be used when none
^ permalink raw reply
* Re: [PATCH] Initialise spinlock in the DEBUG_PAGEALLOC code
From: Michael Ellerman @ 2007-04-18 1:38 UTC (permalink / raw)
To: Milton Miller; +Cc: ppcdev, Paul Mackerras
In-Reply-To: <076a5a3adc4b5b29a3fd2ade48d52184@bga.com>
[-- Attachment #1: Type: text/plain, Size: 936 bytes --]
On Tue, 2007-04-17 at 02:57 -0500, Milton Miller wrote:
> On Tue Apr 17 11:43:12 EST 2007, Michael Ellerman wrote:
> > -static spinlock_t linear_map_hash_lock;
> > +static spinlock_t linear_map_hash_lock = SPIN_LOCK_UNLOCKED;
>
> I think the people in this thread
>
> [KJ][PATCH]SPIN_LOCK_UNLOCKED cleanup in arch/powerpc
> http://ozlabs.org/pipermail/linuxppc-dev/2007-April/034210.html
>
> SPIN_LOCK_UNLOCKED cleanup,use DEFINE_SPINLOCK or
> __SPIN_LOCK_UNLOCKED where ever appropriate.
>
> would like you to initialize it differently. (I think it has
> to do with the lock dependancy stuff).
And it's documented where .. ?
I'll send a new patch.
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 1/4 v2] powerpc: document max-speed and interface-type properties
From: Kim Phillips @ 2007-04-18 1:13 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev
In-Reply-To: <f170b2c44ae8a76dd4d35ceb94a624b0@kernel.crashing.org>
On Wed, 18 Apr 2007 01:18:24 +0200
Segher Boessenkool <segher@kernel.crashing.org> wrote:
> >> "compatible" means "what kind of device is this", for the
> >> purposes of a client program (i.e., Linux) matching a
> >> driver to it (i.e., it should say what kind of PHY it
> >> is, and phylib should use that info -- in most cases,
> >> it won't need more than the least specific entry in
> >> "compatible", i.e. "rgmii" or whatever.
> >>
> >
> > sorry, I disagree; for me, a compatible entry in the PHY node would
> > look
> > something like "marvell"
>
> which would be completely wrong
>
that depends on what degree the manufacturer's PHYs are compatible.
> > or "m88e11x1".
>
> It should be something like "m88e11x1\0m88e1xxx\0rgmii" instead.
m88e11x1 implies rgmii, including all the other interfaces the PHY
supports (gmii, mii, tbi, etc.).
..but I'm not interested in specifying what interfaces the PHY supports.
> A "compatible" property can contain many values, ordered from
> most exact to least exact.
>
> > "rgmii" might indeed be
> > something that PHY supports, but it tells the driver nothing about how
> > to enable it (whereas "m88e11x1" would). The rgmii designation in
> > question in this thread is not a property of the PHY, but of the board.
>
> It certainly is a property of the PHY as well.
>
sure.
> >> So those UCCs should have a different "compatible" entry.
> >> It's not rocket science.
> >
> > It's referring to the name of the driver,
>
> No, not at all. No device tree entry name/value has any
> direct correspondence with Linux device driver names
> (in principle; things can "accidentally" have the same
> name, of course).
well that may be the case here then.
> >> max-speed of connection = min(max-speed of enet, max-speed
> >> of PHY) -- and both of those are implied by their respective
> >> "compatible" properties.
> >>
> >
> > Again, max-speed is exclusively for configuring the UCC itself,
> > regardless of the connection speed.
>
> If that is really true, and the value of that property
> has nothing to do with the MAC<->PHY data channel, it should
> have a different (not that generic) name.
>
can you elaborate on why, including an example of what you'd think would
be a better one?
Kim
^ permalink raw reply
* Re: [PATCH] generic check_legacy_ioport
From: Segher Boessenkool @ 2007-04-17 23:28 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: linuxppc-dev, Olaf Hering
In-Reply-To: <200704172322.23362.arnd@arndb.de>
> I could be wrong, but I think I've seen fake 'isa' bus nodes in the
> device tree
> for machines that don't actually have isa. I probably saw this on very
> early
> cell blades (not the ones currently shipping), but perhaps others have
> made the same mistake.
JS2x SLOF pretends the LPC bus is ISA (although the two
are not completely compatible!) because otherwise
Linux wouldn't find the serial ports. I suppose I could
have fixed the Linux code instead but it was hard enough
to understand already, and really hard to change (since
that would require testing on all previously supported
platforms).
> How about simply defining a new common function like
>
> int generic_deny_legacy_ioport(unsigned long base_port)
> {
> return -EINVAL;
> }
>
> so that not every platform has to define their own but can either
> set ppc_md.check_legacy_ioport to NULL, to generic_deny_legacy_ioport
> or their own function if they do something fancy?
I'd rather deny everything legacy x86 by default, and
only allow a few ranges on the few platforms that really
want that.
Segher
^ permalink raw reply
* Re: [PATCH 1/4 v2] powerpc: document max-speed and interface-type properties
From: Segher Boessenkool @ 2007-04-17 23:18 UTC (permalink / raw)
To: Kim Phillips; +Cc: linuxppc-dev
In-Reply-To: <20070417152712.51c7348f.kim.phillips@freescale.com>
>> "compatible" means "what kind of device is this", for the
>> purposes of a client program (i.e., Linux) matching a
>> driver to it (i.e., it should say what kind of PHY it
>> is, and phylib should use that info -- in most cases,
>> it won't need more than the least specific entry in
>> "compatible", i.e. "rgmii" or whatever.
>>
>
> sorry, I disagree; for me, a compatible entry in the PHY node would
> look
> something like "marvell"
which would be completely wrong
> or "m88e11x1".
It should be something like "m88e11x1\0m88e1xxx\0rgmii" instead.
A "compatible" property can contain many values, ordered from
most exact to least exact.
> "rgmii" might indeed be
> something that PHY supports, but it tells the driver nothing about how
> to enable it (whereas "m88e11x1" would). The rgmii designation in
> question in this thread is not a property of the PHY, but of the board.
It certainly is a property of the PHY as well.
>> So those UCCs should have a different "compatible" entry.
>> It's not rocket science.
>
> It's referring to the name of the driver,
No, not at all. No device tree entry name/value has any
direct correspondence with Linux device driver names
(in principle; things can "accidentally" have the same
name, of course).
>> max-speed of connection = min(max-speed of enet, max-speed
>> of PHY) -- and both of those are implied by their respective
>> "compatible" properties.
>>
>
> Again, max-speed is exclusively for configuring the UCC itself,
> regardless of the connection speed.
If that is really true, and the value of that property
has nothing to do with the MAC<->PHY data channel, it should
have a different (not that generic) name.
Segher
^ permalink raw reply
* [PATCH dtc take 3] Fix reserve map output for asm format.
From: Jerry Van Baren @ 2007-04-17 22:14 UTC (permalink / raw)
To: linuxppc-dev, jdl
Add extra reserve map slots output for asm format (previously done for dtb
output).
Signed-off-by: Gerald Van Baren <vanbaren@cideas.com>
---
Hi Jon, David, Milton,
Here is a patch just to fix the asm output for reserved slots for the
-R parameter.
Best regards,
gvb
flattree.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/flattree.c b/flattree.c
index 151d16e..8159848 100644
--- a/flattree.c
+++ b/flattree.c
@@ -490,6 +490,9 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys)
(unsigned int)(re->re.size >> 32),
(unsigned int)(re->re.size & 0xffffffff));
}
+ for (i = 0; i < reservenum; i++) {
+ fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
+ }
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
--
1.4.4.4
^ permalink raw reply related
* Re: [PATCH] generic check_legacy_ioport
From: Arnd Bergmann @ 2007-04-17 21:22 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Olaf Hering
In-Reply-To: <20070417210745.GA3567@aepfle.de>
On Tuesday 17 April 2007, Olaf Hering wrote:
>=20
> =A0int check_legacy_ioport(unsigned long base_port)
> =A0{
> -=A0=A0=A0=A0=A0=A0=A0if (ppc_md.check_legacy_ioport =3D=3D NULL)
> +=A0=A0=A0=A0=A0=A0=A0struct device_node *np;
> +=A0=A0=A0=A0=A0=A0=A0if (ppc_md.check_legacy_ioport =3D=3D NULL) {
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0np =3D of_find_node_by_type=
(NULL, "isa");
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0if (np =3D=3D NULL)
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0ret=
urn -ENODEV;
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0of_node_put(np);
> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return 0;
> +=A0=A0=A0=A0=A0=A0=A0}
> =A0=A0=A0=A0=A0=A0=A0=A0return ppc_md.check_legacy_ioport(base_port);
> =A0}
I could be wrong, but I think I've seen fake 'isa' bus nodes in the device =
tree
for machines that don't actually have isa. I probably saw this on very early
cell blades (not the ones currently shipping), but perhaps others have
made the same mistake.
How about simply defining a new common function like
int generic_deny_legacy_ioport(unsigned long base_port)
{
return -EINVAL;
}
so that not every platform has to define their own but can either
set ppc_md.check_legacy_ioport to NULL, to generic_deny_legacy_ioport
or their own function if they do something fancy?
Arnd <><
^ permalink raw reply
* [PATCH] generic check_legacy_ioport
From: Olaf Hering @ 2007-04-17 21:07 UTC (permalink / raw)
To: linuxppc-dev
Reject access to legacy ioports unless an isa node exists
check_legacy_ioport makes only sense on PREP, CHRP and pSeries.
They may have an isa node with PS/2, parport, floppy and serial ports.
ipmi calls check_legacy_ioport.
Only cell_defconfig has ipmi enabled.
cell returns -ENODEV per default.
Conclusion: nothing uses ipmi.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
arch/powerpc/kernel/setup-common.c | 8 +++++++-
arch/powerpc/platforms/cell/setup.c | 10 ----------
arch/powerpc/platforms/celleb/setup.c | 10 ----------
arch/powerpc/platforms/iseries/setup.c | 10 ----------
arch/powerpc/platforms/pasemi/setup.c | 7 -------
arch/powerpc/platforms/powermac/setup.c | 10 ----------
arch/powerpc/platforms/pseries/setup.c | 4 ++++
7 files changed, 11 insertions(+), 48 deletions(-)
compile tested.
Index: b/arch/powerpc/kernel/setup-common.c
===================================================================
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -498,8 +498,14 @@ void probe_machine(void)
int check_legacy_ioport(unsigned long base_port)
{
- if (ppc_md.check_legacy_ioport == NULL)
+ struct device_node *np;
+ if (ppc_md.check_legacy_ioport == NULL) {
+ np = of_find_node_by_type(NULL, "isa");
+ if (np == NULL)
+ return -ENODEV;
+ of_node_put(np);
return 0;
+ }
return ppc_md.check_legacy_ioport(base_port);
}
EXPORT_SYMBOL(check_legacy_ioport);
Index: b/arch/powerpc/platforms/cell/setup.c
===================================================================
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -190,15 +190,6 @@ static int __init cell_probe(void)
return 1;
}
-/*
- * Cell has no legacy IO; anything calling this function has to
- * fail or bad things will happen
- */
-static int cell_check_legacy_ioport(unsigned int baseport)
-{
- return -ENODEV;
-}
-
define_machine(cell) {
.name = "Cell",
.probe = cell_probe,
@@ -211,7 +202,6 @@ define_machine(cell) {
.get_rtc_time = rtas_get_rtc_time,
.set_rtc_time = rtas_set_rtc_time,
.calibrate_decr = generic_calibrate_decr,
- .check_legacy_ioport = cell_check_legacy_ioport,
.progress = cell_progress,
.init_IRQ = cell_init_irq,
.pci_setup_phb = rtas_setup_phb,
Index: b/arch/powerpc/platforms/celleb/setup.c
===================================================================
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -128,15 +128,6 @@ static int __init celleb_probe(void)
return 1;
}
-/*
- * Cell has no legacy IO; anything calling this function has to
- * fail or bad things will happen
- */
-static int celleb_check_legacy_ioport(unsigned int baseport)
-{
- return -ENODEV;
-}
-
#ifdef CONFIG_KEXEC
static void celleb_kexec_cpu_down(int crash, int secondary)
{
@@ -173,7 +164,6 @@ define_machine(celleb) {
.get_rtc_time = beat_get_rtc_time,
.set_rtc_time = beat_set_rtc_time,
.calibrate_decr = generic_calibrate_decr,
- .check_legacy_ioport = celleb_check_legacy_ioport,
.progress = celleb_progress,
.power_save = beat_power_save,
.nvram_size = beat_nvram_get_size,
Index: b/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -628,15 +628,6 @@ static void iseries_iounmap(volatile voi
{
}
-/*
- * iSeries has no legacy IO, anything calling this function has to
- * fail or bad things will happen
- */
-static int iseries_check_legacy_ioport(unsigned int baseport)
-{
- return -ENODEV;
-}
-
static int __init iseries_probe(void)
{
unsigned long root = of_get_flat_dt_root();
@@ -667,7 +658,6 @@ define_machine(iseries) {
.calibrate_decr = generic_calibrate_decr,
.progress = iSeries_progress,
.probe = iseries_probe,
- .check_legacy_ioport = iseries_check_legacy_ioport,
.ioremap = iseries_ioremap,
.iounmap = iseries_iounmap,
/* XXX Implement enable_pmcs for iSeries */
Index: b/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -101,12 +101,6 @@ void __init pas_setup_arch(void)
pasemi_idle_init();
}
-/* No legacy IO on our parts */
-static int pas_check_legacy_ioport(unsigned int baseport)
-{
- return -ENODEV;
-}
-
static __init void pas_init_IRQ(void)
{
struct device_node *np;
@@ -237,7 +231,6 @@ define_machine(pas) {
.restart = pas_restart,
.get_boot_time = pas_get_boot_time,
.calibrate_decr = generic_calibrate_decr,
- .check_legacy_ioport = pas_check_legacy_ioport,
.progress = pas_progress,
.machine_check_exception = pas_machine_check_handler,
.pci_irq_fixup = pas_pci_irq_fixup,
Index: b/arch/powerpc/platforms/powermac/setup.c
===================================================================
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -616,15 +616,6 @@ static void __init pmac_init_early(void)
#endif
}
-/*
- * pmac has no legacy IO, anything calling this function has to
- * fail or bad things will happen
- */
-static int pmac_check_legacy_ioport(unsigned int baseport)
-{
- return -ENODEV;
-}
-
static int __init pmac_declare_of_platform_devices(void)
{
struct device_node *np;
@@ -736,7 +727,6 @@ define_machine(powermac) {
.get_rtc_time = pmac_get_rtc_time,
.calibrate_decr = pmac_calibrate_decr,
.feature_call = pmac_do_feature_call,
- .check_legacy_ioport = pmac_check_legacy_ioport,
.progress = udbg_progress,
#ifdef CONFIG_PPC64
.pci_probe_mode = pmac_pci_probe_mode,
Index: b/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -356,6 +356,10 @@ static int pSeries_check_legacy_ioport(u
return -ENODEV;
of_node_put(np);
break;
+ default:
+ printk("%s rejected access to port %u\n", __FUNCTION__, baseport);
+ WARN_ON(baseport);
+ return -ENODEV;
}
return 0;
}
^ permalink raw reply
* Re: [PATCH 1/4 v2] powerpc: document max-speed and interface-type properties
From: Kim Phillips @ 2007-04-17 20:27 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev
In-Reply-To: <788e650fbb3f95eaf1bfb6955f9cef17@kernel.crashing.org>
On Tue, 17 Apr 2007 12:25:51 +0200
Segher Boessenkool <segher@kernel.crashing.org> wrote:
> >> You can put "rgmii" or whatever in the "compatible" property
> >> as well.
> >>
> > I don't understand how intermixing PHY device compatibility with the
> > UCC connection to the PHY would be a good thing.
>
> "compatible" means "what kind of device is this", for the
> purposes of a client program (i.e., Linux) matching a
> driver to it (i.e., it should say what kind of PHY it
> is, and phylib should use that info -- in most cases,
> it won't need more than the least specific entry in
> "compatible", i.e. "rgmii" or whatever.
>
sorry, I disagree; for me, a compatible entry in the PHY node would look
something like "marvell" or "m88e11x1". "rgmii" might indeed be
something that PHY supports, but it tells the driver nothing about how
to enable it (whereas "m88e11x1" would). The rgmii designation in
question in this thread is not a property of the PHY, but of the board.
> >>> If I were to put the properties in the PHY node, I wouldn't be able
> >>> to
> >>> describe a 1000Mbit/s capable UCC connected to a 100Mbit/s capable
> >>> PHY,
> >>> or vice versa.
> >>
> >> Of course you can. The "compatible" in the enet node
> >> implies it can do 1000Mbps; the "compatible" in the
> >> PHY node implies it does 100Mbps.
> >
> > compatible in the UCC node is currently set to "ucc_geth", which does
> > not necessarily imply that that UCC can do 1000Mbit/s. Some UCCs can
> > only do 100Mbit/s.
>
> So those UCCs should have a different "compatible" entry.
> It's not rocket science.
>
It's referring to the name of the driver, as is compatible "gianfar".
other values could be "fsl_atm" or "ucc_uart", or whatever other
communications protocol a UCC can manage (to which, btw, max-speed would
be easily extensible).
> > We currently do not have hardware that connects UCC with max-speed x
> > with a PHY with max. speed capability of y, where x != y, so there is
> > currently no need to specify the speed of the PHY. Not that that would
> > be needed; the phylib would call ucc_geth's adjust_link with the new
> > speed. Note that the max-speed property is used to set registers in
> > the
> > UCC only.
>
> max-speed of connection = min(max-speed of enet, max-speed
> of PHY) -- and both of those are implied by their respective
> "compatible" properties.
>
Again, max-speed is exclusively for configuring the UCC itself,
regardless of the connection speed.
Kim
^ permalink raw reply
* Re: Xilinx Virtex git tree
From: Grant Likely @ 2007-04-17 18:32 UTC (permalink / raw)
To: Mohammad Sadegh Sadri
Cc: Andrei Konovalov, Miroslaw Dach, linuxppc-embedded, Duane Snider
In-Reply-To: <BAY115-W21A26421AC818933E85766B2510@phx.gbl>
On 4/17/07, Mohammad Sadegh Sadri <mamsadegh@hotmail.com> wrote:
>
> Great work Grant
>
> Really thanks for your efforts
>
> specially helping beginners and making the development process much more easier for them
>
> by the way, montavista's git tree is too old, ( more 10 months ) why they do not update their git tree? ( may be andrei can answer this? )
You could also ask me why it took 2 years to clean up the mess I made
out of virtex support in mainline. :-) This stuff takes time to sort
out, and when there is more work than time to do it in, things are
bound to get dropped on the floor.
Cheers,
g.
--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* RE: Xilinx Virtex git tree
From: Mohammad Sadegh Sadri @ 2007-04-17 17:38 UTC (permalink / raw)
To: Grant Likely, Duane Snider, Andrei Konovalov, Miroslaw Dach,
Peter Mendham, linuxppc-embedded
Great work Grant
Really thanks for your efforts
specially helping beginners and making the development process much more ea=
sier for them
by the way, montavista's git tree is too old, ( more 10 months ) why they d=
o not update their git tree? ( may be andrei can answer this? )
----------------------------------------
> Date: Tue, 17 Apr 2007 10:05:20 -0600
> From: grant.likely@secretlab.ca
> To: dsnider@rgbnetworks.com; mamsadegh@hotmail.com; akonovalov@ru.mvista.=
com; miroslaw.dach@psi.ch; petermendham@computing.dundee.ac.uk; linuxppc-em=
bedded@ozlabs.org
> Subject: Xilinx Virtex git tree
>=20
> For those of you who are interested, I've published my linux-2.6 git
> tree with patches for Xilinx Virtex support including the TEMAC and
> SystemACE drivers.
>=20
> You can find it at http://git.secretlab.ca
>=20
> Cheers,
> g.
>=20
> --=20
> Grant Likely, B.Sc. P.Eng.
> Secret Lab Technologies Ltd.
> grant.likely@secretlab.ca
> (403) 399-0195
_________________________________________________________________
Connect to the next generation of MSN Messenger=A0
http://imagine-msn.com/messenger/launch80/default.aspx?locale=3Den-us&sourc=
e=3Dwlmailtagline=
^ permalink raw reply
* Re: Compiling interrupt controller code as a module
From: Bill Gatliff @ 2007-04-17 17:13 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: Linuxppc-embedded
In-Reply-To: <200704171731.43608.laurent.pinchart@technotrade.biz>
Laurent Pinchart wrote:
> Hi everybody.
>
> I wrote a kernel driver for a custom bus (using arch/ppc). The hardware has a
> cascaded interrupt controller wired to one of the CPU interrupts. The
> interrupt controller IRQ handler calls __do_IRQ() to dispatch interrupts.
>
> Everything worked fine until I tried to compile the code as a module because
> __do_IRQ() is not exported. Is there a way to compile an interrupt controller
> as a module, or must it be included in the kernel ?
>
Could you just export __do_IRQ()?
b.g.
--
Bill Gatliff
bgat@billgatliff.com
^ permalink raw reply
* Re: [PATCH 3/4] bootwrapper: Add ppcboot.h.
From: Scott Wood @ 2007-04-17 16:35 UTC (permalink / raw)
To: Wolfgang Denk; +Cc: linuxppc-dev, paulus
In-Reply-To: <20070417090342.3E736352658@atlas.denx.de>
Wolfgang Denk wrote:
> In message <20070416232553.GB26693@ld0162-tx32.am.freescale.net> you wrote:
>>diff --git a/arch/powerpc/boot/ppcboot.h b/arch/powerpc/boot/ppcboot.h
>>new file mode 100644
>>index 0000000..5290ff2
>>--- /dev/null
>>+++ b/arch/powerpc/boot/ppcboot.h
>
>
> Shouldn't we finally get this straight and call the file "u-boot.h" as
> it is called in U-Boot?
Probably... though the ppcboot.h name does reinforce the legacy nature
of the interface. Maybe old-u-boot.h?
Paul, feel free to change the name of the file in the patch if you want.
-Scott
^ permalink raw reply
* Xilinx Virtex git tree
From: Grant Likely @ 2007-04-17 16:05 UTC (permalink / raw)
To: Duane Snider, Mohammad Sadegh Sadri, Andrei Konovalov,
Miroslaw Dach, Peter Mendham, linuxppc-embedded
For those of you who are interested, I've published my linux-2.6 git
tree with patches for Xilinx Virtex support including the TEMAC and
SystemACE drivers.
You can find it at http://git.secretlab.ca
Cheers,
g.
--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* Compiling interrupt controller code as a module
From: Laurent Pinchart @ 2007-04-17 15:31 UTC (permalink / raw)
To: Linuxppc-embedded
Hi everybody.
I wrote a kernel driver for a custom bus (using arch/ppc). The hardware has a
cascaded interrupt controller wired to one of the CPU interrupts. The
interrupt controller IRQ handler calls __do_IRQ() to dispatch interrupts.
Everything worked fine until I tried to compile the code as a module because
__do_IRQ() is not exported. Is there a way to compile an interrupt controller
as a module, or must it be included in the kernel ?
Best regards,
Laurent Pinchart
^ permalink raw reply
* RE: Variable "current" in Linux kernel...
From: Siva Prasad @ 2007-04-17 15:12 UTC (permalink / raw)
To: Phillip Lougher; +Cc: linuxppc-dev, linuxppc-embedded
In-Reply-To: <bffbecbb0704161552p7f62c800kd774809a41f177f0@mail.gmail.com>
One question for the community:
Why are we storing the physical address of a task. Why can't we store
the virtual address, and convert it as and when required by using
tophys(). By storing the physical address, are we not loosing this code
portability. May be I am wrong, but would like to understand.
Thanks Phillip.
Now even the bootmem code needs update, as that considers 0x00000000 as
default lower address and does the computations for free memory based on
that.
Thanks every one for the help.
Thanks
Siva
-----Original Message-----
From: Phillip Lougher [mailto:phillip.lougher@gmail.com]=20
Sent: Monday, April 16, 2007 3:53 PM
To: Siva Prasad
Cc: linuxppc-dev@ozlabs.org; linuxppc-embedded@ozlabs.org
Subject: Re: Variable "current" in Linux kernel...
On 4/16/07, Siva Prasad <sprasad@bivio.net> wrote:
>
> I would like to know where exactly the value of variable "current"
gets
> changed.
current points to the task_struct structure of the currently running
process. It, obviously, changes each time the scheduler schedules
another process.
>
>
> BTW... did any one tried before to run from a different location of
memory
> than the usual 0x00000000? What are the main problems you faced? I
know this
> is open ended question, but wanted to see if any one ever did that.
>
I changed the 2.4 PPC kernel to do this about 5 years ago (for
Zarlink). Most of the issues relate to the PPC specific code, all
functions which map from a va->pa, from a pte->va, and vice-versa have
to be changed. The early start up assembly code has to be aware the
kernel is not running at zero, specifically the code which creates the
initial TLB entries. As far as I can recall, only one line of non-PPC
specific code needed to be changed. It is, however, a difficult task
which requires careful auditing of the code, and obviously knowledge
of the vm and memory allocator systems.
Phillip
^ permalink raw reply
* [PATCH 2/2] hvc_console typo fixes
From: Will Schmidt @ 2007-04-17 14:54 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras; +Cc: willschm
In-Reply-To: <1176821087.28514.145.camel@farscape.rchland.ibm.com>
Fix a handful of comment typos for hvc_console.
Signed-off-by: Will Schmidt <will_schmidt@vnet.ibm.com>
---
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index fc9bc77..0f9ed7b 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -102,12 +102,12 @@ static DEFINE_SPINLOCK(hvc_structs_lock)
/*
* This value is used to assign a tty->index value to a hvc_struct based
* upon order of exposure via hvc_probe(), when we can not match it to
- * a console canidate registered with hvc_instantiate().
+ * a console candidate registered with hvc_instantiate().
*/
static int last_hvc = -1;
/*
- * Do not call this function with either the hvc_strucst_lock or the hvc_struct
+ * Do not call this function with either the hvc_structs_lock or the hvc_struct
* lock held. If successful, this function increments the kobject reference
* count against the target hvc_struct so it should be released when finished.
*/
@@ -160,7 +160,7 @@ void hvc_console_print(struct console *c
if (index >= MAX_NR_HVC_CONSOLES)
return;
- /* This console adapter was removed so it is not useable. */
+ /* This console adapter was removed so it is not usable. */
if (vtermnos[index] < 0)
return;
@@ -218,7 +218,7 @@ struct console hvc_con_driver = {
};
/*
- * Early console initialization. Preceeds driver initialization.
+ * Early console initialization. Precedes driver initialization.
*
* (1) we are first, and the user specified another driver
* -- index will remain -1
@@ -255,7 +255,7 @@ int hvc_instantiate(uint32_t vtermno, in
if (vtermnos[index] != -1)
return -1;
- /* make sure no no tty has been registerd in this index */
+ /* make sure no no tty has been registered in this index */
hp = hvc_get_by_index(index);
if (hp) {
kobject_put(&hp->kobj);
@@ -265,7 +265,7 @@ int hvc_instantiate(uint32_t vtermno, in
vtermnos[index] = vtermno;
cons_ops[index] = ops;
- /* reserve all indices upto and including this index */
+ /* reserve all indices up to and including this index */
if (last_hvc < index)
last_hvc = index;
@@ -526,7 +526,7 @@ static int hvc_write(struct tty_struct *
/*
* This is actually a contract between the driver and the tty layer outlining
- * how much write room the driver can guarentee will be sent OR BUFFERED. This
+ * how much write room the driver can guarantee will be sent OR BUFFERED. This
* driver MUST honor the return value.
*/
static int hvc_write_room(struct tty_struct *tty)
@@ -813,7 +813,7 @@ int __devexit hvc_remove(struct hvc_stru
/*
* We 'put' the instance that was grabbed when the kobject instance
- * was intialized using kobject_init(). Let the last holder of this
+ * was initialized using kobject_init(). Let the last holder of this
* kobject cause it to be removed, which will probably be the tty_hangup
* below.
*/
@@ -869,7 +869,7 @@ int __init hvc_init(void)
}
module_init(hvc_init);
-/* This isn't particularily necessary due to this being a console driver
+/* This isn't particularly necessary due to this being a console driver
* but it is nice to be thorough.
*/
static void __exit hvc_exit(void)
^ permalink raw reply related
* [PATCH 1/2] hvc_console polling mode timer backoff
From: Will Schmidt @ 2007-04-17 14:44 UTC (permalink / raw)
To: ppcdev, Paul Mackerras
Paulus, I think this is ready to go, please apply, thanks.
Add a back-off mechanism to hvc_console's polling logic. This change
drops the timers/second ratio from ~90 to ~1/2 while the console is
idle.
This change is most noticeable when watching /proc/timer_stats output.
This only affects when the hvc_console is running in poll mode, i.e.
power4 and cell systems.
I've tested on Power4, Michael Ellerman has both contributed to the
patch and tested on cell.
Signed-off-by: Will Schmidt <will_schmidt@vnet.ibm.com>
cc: Michael Ellerman <michael@ellerman.id.au>
---
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index a0a88aa..fc9bc77 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -47,8 +47,6 @@ #include "hvc_console.h"
#define HVC_MAJOR 229
#define HVC_MINOR 0
-#define TIMEOUT (10)
-
/*
* Wait this long per iteration while trying to push buffered data to the
* hypervisor before allowing the tty to complete a close operation.
@@ -550,6 +548,18 @@ static int hvc_chars_in_buffer(struct tt
return hp->n_outbuf;
}
+/*
+ * timeout will vary between the MIN and MAX values defined here. By default
+ * and during console activity we will use a default MIN_TIMEOUT of 10. When
+ * the console is idle, we increase the timeout value on each pass through
+ * msleep until we reach the max. This may be noticeable as a brief (average
+ * one second) delay on the console before the console responds to input when
+ * there has been no input for some time.
+ */
+#define MIN_TIMEOUT (10)
+#define MAX_TIMEOUT (2000)
+static u32 timeout = MIN_TIMEOUT;
+
#define HVC_POLL_READ 0x00000001
#define HVC_POLL_WRITE 0x00000002
@@ -642,9 +652,14 @@ #endif /* CONFIG_MAGIC_SYSRQ */
bail:
spin_unlock_irqrestore(&hp->lock, flags);
- if (read_total)
+ if (read_total) {
+ /* Activity is occurring, so reset the polling backoff value to
+ a minimum for performance. */
+ timeout = MIN_TIMEOUT;
+
tty_flip_buffer_push(tty);
-
+ }
+
return poll_mask;
}
@@ -688,8 +703,12 @@ int khvcd(void *unused)
if (!hvc_kicked) {
if (poll_mask == 0)
schedule();
- else
- msleep_interruptible(TIMEOUT);
+ else {
+ if (timeout < MAX_TIMEOUT)
+ timeout += (timeout >> 6) + 1;
+
+ msleep_interruptible(timeout);
+ }
}
__set_current_state(TASK_RUNNING);
} while (!kthread_should_stop());
^ permalink raw reply related
* RE: Problem cloning Linus' GIT tree!
From: Gerald Ruescher @ 2007-04-17 14:09 UTC (permalink / raw)
To: Linuxppc-embedded
In-Reply-To: <200704171228.56848.laurent.pinchart@technotrade.biz>
Dear Laurent,
> > After a while however, git exits with the following error message:
> >
> > error: Couldn't get =
http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/ref=
s/tags/v2.6.11 for tags/v2.6.11=20
> > The requested URL returned error: 404
> > error: Could not interpret tags/v2.6.11 as something to pull
> > rm: cannot remove directory
> > `/cygdrive/c/home/git/linux-2.6/.git/clone-tmp': Directory not =
empty
>
> Try upgrading git to the last version.
I'm already using the latest version (1.5.1) of git but the error still =
persists.
A "http 404" error usually reports that something is missing on the =
server.
In fact, if I copy the URL above to web browser, the same error occurs.
Question:=20
Do=20
git://git.kernel.org=20
and http://www.kernel.org <-- Note the *www*(!)
physically access the same repository? Or is the http server maybe just
a mirror of the git server (which could mean that the two could be out =
of sync)
If all fails I could harass our company's network admins to open
the git port in the firewall :-) but I'd prefer to fetch the tree
via http.
Any advice? Is there anyone else who is using Linus' tree via http?
Many thanks and kind regards,
Gerald
_______________________________________________
Gerald R=FCscher
Software Development Engineer
Core Real-Time Implementation
dSPACE GmbH Tel.: +49 5251 1638-1826
Technologiepark 25 Fax: +49 5251 16198-1826
33100 Paderborn http://www.dspace.de
Germany mailto:GRuescher@dspace.de
_______________________________________________
^ permalink raw reply
* Re: Problem cloning Linus' GIT tree!
From: Laurent Pinchart @ 2007-04-17 13:31 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <18A49CF3586FC14290887ECC63C9141F0104D047@exchange2003.dspace.de>
> > > After a while however, git exits with the following error message:
> > >
> > > error: Couldn't get
> > > http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/r
> > >efs/tags/v2.6.11 for tags/v2.6.11 The requested URL returned error: 404
> > > error: Could not interpret tags/v2.6.11 as something to pull
> > > rm: cannot remove directory
> > > `/cygdrive/c/home/git/linux-2.6/.git/clone-tmp': Directory not empty
> >
> > Try upgrading git to the last version.
>
> I'm already using the latest version (1.5.1) of git but the error still
> persists. A "http 404" error usually reports that something is missing on
> the server. In fact, if I copy the URL above to web browser, the same error
> occurs.
I had the same issue some time ago. Git used to store tags in the .git/tags
directory. Linus repository has somehow been 'stripped' from those tags,
which are now stored in the git objects (I'm not sure if the repository has
been stripped on purpose, or if the .git/tags directory is just deprecated).
I thought upgrading to a newer git release had fixed the problem, but after
checking it turns out I had to switch to git:// as well. The http:// protocol
might not support stripped repositories.
> Question:
>
> Do
> git://git.kernel.org
> and http://www.kernel.org <-- Note the *www*(!)
>
> physically access the same repository? Or is the http server maybe just
> a mirror of the git server (which could mean that the two could be out of
> sync)
I'm not sure about that. The http repository is not broken, it's just
stripped. The http:// protocol handler in git might need to be fixed.
> If all fails I could harass our company's network admins to open
> the git port in the firewall :-) but I'd prefer to fetch the tree
> via http.
>
> Any advice? Is there anyone else who is using Linus' tree via http?
You could ask on the git mailing list or IRC channel.
Best regards,
Laurent Pinchart
^ permalink raw reply
* [RFC 3/3] cryptoapi: speed test
From: Sebastian Siewior @ 2007-04-17 11:52 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070417115206.709701000@linux.vnet.ibm.com>
This has been used for performance testing of my aes altivec code.
Signed-off-by: Sebastian Siewior <bigeasy@linux.vnet.ibm.com>
Index: linux/crypto/limi-speed.c
===================================================================
--- /dev/null
+++ linux/crypto/limi-speed.c
@@ -0,0 +1,140 @@
+/*
+ * Code derived von crypt/tcrypt.h
+ *
+ * Small speed test with time resolution in msec.
+ * Author: Sebastian Siewior (bigeasy _at_ breakpoint.cc)
+ * License: GPL v2
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <linux/jiffies.h>
+#include <linux/types.h>
+
+static char *in;
+
+static unsigned int buff_size = 16 * 1024;
+module_param(buff_size, uint, 0444);
+MODULE_PARM_DESC(buff_size, "Buffer allocated by kmalloc()");
+
+static unsigned int keylen = 16;
+module_param(keylen, uint, 0444);
+MODULE_PARM_DESC(keylen, "Length of the key (16,24 or 32 bits");
+
+static unsigned int mode = 0;
+module_param(mode, uint, 0444);
+MODULE_PARM_DESC(mode, "0 -> encryption else decryption");
+
+static unsigned int big_loops = 10;
+module_param(big_loops, uint, 0444);
+MODULE_PARM_DESC(big_loops, "Number of mensurations.");
+
+static unsigned int small_loops = 10000;
+module_param(small_loops, uint, 0444);
+MODULE_PARM_DESC(small_loops, "loops within one mesurement.");
+
+static unsigned int alg = 1;
+module_param(alg, uint, 0444);
+MODULE_PARM_DESC(alg, "0 -> ecb(aes), else -> cbc(aes)");
+
+static int __init init(void)
+{
+ struct scatterlist sg[1];
+ struct crypto_blkcipher *tfm;
+ struct blkcipher_desc desc;
+ unsigned int i;
+ unsigned int ret;
+ unsigned int iv_len;
+ unsigned long start, end;
+ unsigned long total = 0;
+ unsigned long size_kb;
+ unsigned char key[32] = { 1, 2, 3, 4, 5, 6 };
+ const unsigned char *algname;
+
+ algname = alg ? "cbc(aes)" : "ecb(aes)";
+ printk("Limi-speed: %s buff_size: %u, keylen: %d, mode: %s\n", algname, buff_size, keylen,
+ mode ? "decryption" : "encryption");
+ printk("loops: %d, iterations: %d, ", big_loops, small_loops);
+ size_kb = small_loops * buff_size / 1024;
+ printk("=> %lu kb or %lu mb a loop\n", size_kb, size_kb/1024);
+
+ if (keylen != 16 && keylen != 24 && keylen != 32) {
+ printk("Invalid keysize\n");
+ return -EINVAL;
+ }
+
+ in = kmalloc(buff_size, GFP_KERNEL);
+ if (in == NULL) {
+ printk("Failed to allocate memory.\n");
+ return -ENOMEM;
+ }
+
+ memset(in, 0x24, buff_size);
+
+ sg_set_buf(sg, in, buff_size);
+
+ tfm = crypto_alloc_blkcipher(algname, 0, CRYPTO_ALG_ASYNC);
+
+ if (IS_ERR(tfm)) {
+ printk("failed to load transform for %s: %ld\n", algname, PTR_ERR(tfm));
+ goto leave;
+ }
+
+ crypto_blkcipher_setkey(tfm, key, keylen);
+
+ iv_len = crypto_blkcipher_ivsize(tfm);
+ if (iv_len)
+ crypto_blkcipher_set_iv(tfm, in, iv_len);
+
+ desc.tfm = tfm;
+ desc.flags = 0;
+
+ for (i=0 ; i<big_loops; i++) {
+ int j;
+ start = jiffies;
+ ret = 0;
+
+ for (j=0; j < small_loops && !ret; j++) {
+
+ if (!mode)
+ ret = crypto_blkcipher_encrypt(&desc, sg, sg, buff_size);
+ else
+ ret = crypto_blkcipher_decrypt(&desc, sg, sg, buff_size);
+ }
+
+ if (ret) {
+ printk("encryption failed: %d after (i,j) (%u,%u) iterations\n", ret, i, j);
+ goto leave_loop;
+ }
+ end = jiffies;
+ if ( !time_after(start, end)) {
+ printk("Run: %u msec\n", jiffies_to_msecs(end - start));
+ total += jiffies_to_msecs(end - start);
+ } else {
+ printk("Run: %u msec\n", jiffies_to_msecs(start - end));
+ total += jiffies_to_msecs(start - end);
+ }
+ }
+
+ total /= big_loops;
+ size_kb *= 1000;
+ size_kb /= total;
+ printk("Average: %lu msec, approx. %lu kb/sec || %lu mb/sec \n", total,
+ size_kb, size_kb/1024);
+
+leave_loop:
+ crypto_free_blkcipher(tfm);
+
+leave:
+ kfree(in);
+ return -ENODEV;
+}
+
+static void __exit fini(void) { }
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
Index: linux/crypto/Kconfig
===================================================================
--- linux.orig/crypto/Kconfig
+++ linux/crypto/Kconfig
@@ -462,6 +462,12 @@ config CRYPTO_TEST
help
Quick & dirty crypto test module.
+config CRYPTO_LIMI_SPEED
+ tristate "Crypto algorithm speed test with msec resolution"
+ help
+ insmod/modprobe the module, and watch dmesg for results.
+ Test is for aes only, see modinfo for options
+
source "drivers/crypto/Kconfig"
endif # if CRYPTO
Index: linux/crypto/Makefile
===================================================================
--- linux.orig/crypto/Makefile
+++ linux/crypto/Makefile
@@ -52,3 +52,4 @@ obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
CFLAGS_aes-altivec.o += -O3 -maltivec
aes_altivec-objs := aes-alti.o aes-altivec.o
obj-$(CONFIG_CRYPTO_AES_ALTIVEC) += aes_altivec.o
+obj-$(CONFIG_CRYPTO_LIMI_SPEED) += limi-speed.o
--
^ permalink raw reply
* [RFC 1/3] cryptoapi: AES with AltiVec support
From: Sebastian Siewior @ 2007-04-17 11:52 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070417115206.709701000@linux.vnet.ibm.com>
The aes module supports now CBC & ECB block mode, the performance improves
for encryption, decyption remains the same. There is no difference between
CBC and ECB cipher mode (128b):
ECB encryption: Average: 3172 msec, approx. 50441 kb/sec || 49 mb/sec
ECB decryption: Average: 5330 msec, approx. 30018 kb/sec || 29 mb/sec
CBC encryption: Average: 3185 msec, approx. 50235 kb/sec || 49 mb/sec
CBC decryption: Average: 5362 msec, approx. 29839 kb/sec || 29 mb/sec
The generic code performs better:
ECB encryption: Average: 3058 msec, approx. 52321 kb/sec || 51 mb/sec
ECB decryption: Average: 3058 msec, approx. 52321 kb/sec || 51 mb/sec
CBC encryption: Average: 3696 msec, approx. 43290 kb/sec || 42 mb/sec
CBC decryption: Average: 3706 msec, approx. 43173 kb/sec || 42 mb/sec
It would be nice if someone could play around with different machines.
This numbers are from a ps3.
Signed-off-by: Sebastian Siewior <bigeasy@linux.vnet.ibm.com>
Index: linux/crypto/aes-alti.c
===================================================================
--- /dev/null
+++ linux/crypto/aes-alti.c
@@ -0,0 +1,274 @@
+/*
+ * based on crypto/aes.c
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <crypto/algapi.h>
+
+#include "aes-altivec.h"
+
+#define AES_MIN_KEY_SIZE 16
+#define AES_MAX_KEY_SIZE 32
+
+#define AES_BLOCK_SIZE 16
+
+/* max rounds is 14. Every round needs 1 vector as key (=4 ints or 16 bytes)
+ * The first slot is the given key
+ */
+
+#define MAX_AES_ROUNDS 15
+#define MAX_AES_KEYSIZE_INT (MAX_AES_ROUNDS *4)
+#define MAX_AES_KEYSIZE_BYTE (MAX_AES_KEYSIZE_INT *4)
+#define ENCRYPT 0
+#define DECRYPT 1
+
+struct aes_ctx {
+ unsigned char key_enc_ch[MAX_AES_KEYSIZE_BYTE] __attribute__ ((aligned (16)));
+ unsigned char key_dec_ch[MAX_AES_KEYSIZE_BYTE] __attribute__ ((aligned (16)));
+ unsigned int key_length;
+};
+
+static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ unsigned int key_len)
+{
+ struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ u32 *flags = &tfm->crt_flags;
+ u32 i;
+
+ switch (key_len) {
+ case 16:
+ case 24:
+ case 32:
+ break;
+
+ default:
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+ preempt_disable();
+ enable_kernel_altivec();
+
+ ctx->key_length = key_len;
+ i = expand_key(in_key, key_len/4 , ctx->key_enc_ch, ctx->key_dec_ch);
+
+ preempt_enable();
+ return i;
+}
+
+static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+ const struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ preempt_disable();
+ enable_kernel_altivec();
+
+ aes_encrypt_altivec(in, out, ctx->key_enc_ch, ctx->key_length);
+
+ preempt_enable();
+}
+
+static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+ const struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ preempt_disable();
+ enable_kernel_altivec();
+
+ aes_decrypt_altivec(in, out, ctx->key_dec_ch, ctx->key_length);
+
+ preempt_enable();
+}
+
+static struct crypto_alg aes_alg = {
+ .cra_name = "aes",
+ .cra_driver_name = "aes-altivec",
+ .cra_priority = 123,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct aes_ctx),
+ .cra_alignmask = 15,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cia_setkey = aes_set_key,
+ .cia_encrypt = aes_encrypt,
+ .cia_decrypt = aes_decrypt
+ }
+ }
+};
+
+/*
+ * The fn pointer is the last parameter, the remaining parameter are in caller's order.
+ * That way the compiler must not reorder everything :)
+ */
+static int mode_aes_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes,
+ int (*fn) (const unsigned char *in,
+ unsigned char *out, const unsigned char *kp, unsigned int key_len,
+ unsigned int len, unsigned char *iv_), unsigned int mode)
+{
+ struct aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+ const unsigned char *kp;
+ int ret;
+ u8 *out, *in;
+
+ kp = mode == ENCRYPT ? ctx->key_enc_ch : ctx->key_dec_ch;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ ret = blkcipher_walk_virt(desc, &walk);
+
+ preempt_disable();
+ enable_kernel_altivec();
+
+ while ((nbytes = walk.nbytes)) {
+ /* only use complete blocks */
+ unsigned int n = nbytes & ~(15);
+
+ out = walk.dst.virt.addr;
+ in = walk.src.virt.addr;
+
+ nbytes = fn(in, out, kp, ctx->key_length, n, walk.iv);
+
+ nbytes &= 15;
+ ret = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+
+ preempt_enable();
+ return ret;
+}
+
+static int aes_encrypt_ecb(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return mode_aes_crypt(desc, dst, src, nbytes, aes_encrypt_ecb_altivec, ENCRYPT);
+}
+
+static int aes_decrypt_ecb(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return mode_aes_crypt(desc, dst, src, nbytes, aes_decrypt_ecb_altivec, DECRYPT);
+}
+
+static struct crypto_alg aes_ecb_alg = {
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-altivec",
+ .cra_priority = 125,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_alignmask = 15,
+ .cra_ctxsize = sizeof(struct aes_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(aes_ecb_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = aes_set_key,
+ .encrypt = aes_encrypt_ecb,
+ .decrypt = aes_decrypt_ecb,
+ }
+ }
+};
+
+static int aes_encrypt_cbc(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return mode_aes_crypt(desc, dst, src, nbytes, aes_encrypt_cbc_altivec, ENCRYPT);
+}
+
+static int aes_decrypt_cbc(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ return mode_aes_crypt(desc, dst, src, nbytes, aes_decrypt_cbc_altivec, DECRYPT);
+}
+
+static struct crypto_alg aes_cbc_alg = {
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-altivec",
+ .cra_priority = 125,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_alignmask = 15,
+ .cra_ctxsize = sizeof(struct aes_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(aes_ecb_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = aes_set_key,
+ .encrypt = aes_encrypt_cbc,
+ .decrypt = aes_decrypt_cbc,
+ .ivsize = AES_BLOCK_SIZE,
+ }
+ }
+};
+
+static int __init aes_init(void)
+{
+ unsigned int ret;
+
+ if (!(cpu_has_feature(CPU_FTR_ALTIVEC))) {
+ printk("aes-alti: No altivec unit available\n");
+ return -ENODEV;
+ }
+#ifdef CONFIG_CRYPTO_AES_ALTIVEC_TABLE
+ printk("Table lookup mode\n");
+#endif
+
+ ret = crypto_register_alg(&aes_alg);
+ if (ret) {
+ printk("Failed to register aes\n");
+ goto failed_aes;
+ }
+
+ ret = crypto_register_alg(&aes_ecb_alg);
+ if (ret) {
+ printk("Failed to register aes-ecb\n");
+ goto failed_aes_ecb;
+ }
+
+ ret = crypto_register_alg(&aes_cbc_alg);
+ if (ret) {
+ printk("Failed to register aes-cbc\n");
+ goto failed_aes_cbc;
+ }
+
+ return 0;
+
+failed_aes_cbc:
+ crypto_unregister_alg(&aes_ecb_alg);
+
+failed_aes_ecb:
+ crypto_unregister_alg(&aes_alg);
+
+failed_aes:
+ return -ENODEV;
+}
+
+static void __exit aes_fini(void)
+{
+ crypto_unregister_alg(&aes_alg);
+ crypto_unregister_alg(&aes_ecb_alg);
+ crypto_unregister_alg(&aes_cbc_alg);
+}
+
+module_init(aes_init);
+module_exit(aes_fini);
+
+MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
+MODULE_LICENSE("GPL");
Index: linux/crypto/aes-altivec.c
===================================================================
--- /dev/null
+++ linux/crypto/aes-altivec.c
@@ -0,0 +1,799 @@
+/*
+ * AES implementation with AltiVec support.
+ * v.02
+ *
+ * Author:
+ * Sebastian Siewior (bigeasy _at_ breakpoint.cc)
+ * Arnd Bergmann (arnd _at_ arndb.de)
+ *
+ * License: GPL v2
+ *
+ * Code based on ideas from "Effincient Galois Field Arithmetic on SIMD Architectures" by
+ * Raghav Bhaskar, Prapdeep K. Dubey, Vijay Kumar, Atri Rudra and Animesh Sharma.
+ *
+ * This implementation makes use of AltiVec and asumes therefore big endian (on the other
+ * hand only Intel makes it (still) wrong (well it made porting to 64bit probably a lot of
+ * easier)).
+ * Tables for MixColumn() and InvMixColumn() are adjusted in order to omit ShiftRow in all but
+ * last round.
+ */
+
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <altivec.h>
+#include <linux/autoconf.h>
+#include "aes-altivec.h"
+
+static const vector unsigned char imm_7Fh = {
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f
+};
+
+/*
+ * This values are either defined in AES standard or can be
+ * computed.
+ */
+static const unsigned int Rcon[] = {
+ 0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1b000000,
+ 0x36000000
+};
+
+static const vector unsigned char sbox_enc[16] = {
+ { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 },
+ { 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 },
+ { 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 },
+ { 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 },
+ { 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 },
+ { 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf },
+ { 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 },
+ { 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 },
+ { 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 },
+ { 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb },
+ { 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 },
+ { 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 },
+ { 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a },
+ { 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e },
+ { 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf },
+ { 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }
+};
+
+static const vector unsigned char shift_round = {
+ 0x00, 0x05, 0x0a, 0x0f,
+ 0x04, 0x09, 0x0e, 0x03,
+ 0x08, 0x0d, 0x02, 0x07,
+ 0x0c, 0x01, 0x06, 0x0b
+};
+
+static const vector unsigned char pre_xor_s0 = {
+ 0x10, 0x00, 0x00, 0x10,
+ 0x14, 0x04, 0x04, 0x14,
+ 0x18, 0x08, 0x08, 0x18,
+ 0x1c, 0x0c, 0x0c, 0x1c
+};
+
+static const vector unsigned char pre_xor_s1 = {
+ 0x15, 0x15, 0x05, 0x00,
+ 0x19, 0x19, 0x09, 0x04,
+ 0x1d, 0x1d, 0x0d, 0x08,
+ 0x11, 0x11, 0x01, 0x0c
+};
+
+static const vector unsigned char pre_xor_s2 = {
+ 0x05, 0x1a, 0x1a, 0x05,
+ 0x09, 0x1e, 0x1e, 0x09,
+ 0x0d, 0x12, 0x12, 0x0d,
+ 0x01, 0x16, 0x16, 0x01
+};
+
+static const vector unsigned char pre_xor_s3 = {
+ 0x0a, 0x0a, 0x1f, 0x0a,
+ 0x0e, 0x0e, 0x13, 0x0e,
+ 0x02, 0x02, 0x17, 0x02,
+ 0x06, 0x06, 0x1b, 0x06
+};
+
+static const vector unsigned char pre_xor_s4 = {
+ 0x0f, 0x0f, 0x0f, 0x1f,
+ 0x03, 0x03, 0x03, 0x13,
+ 0x07, 0x07, 0x07, 0x17,
+ 0x0b, 0x0b, 0x0b, 0x1b
+};
+
+static const vector unsigned char sbox_dec[16] = {
+ { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
+ 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb },
+ { 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
+ 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb },
+ { 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
+ 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e },
+ { 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
+ 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 },
+ { 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 },
+ { 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
+ 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 },
+ { 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
+ 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 },
+ { 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
+ 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b },
+ { 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
+ 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 },
+ { 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
+ 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e },
+ { 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
+ 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b },
+ { 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
+ 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 },
+ { 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
+ 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f },
+ { 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
+ 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef },
+ { 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
+ 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 },
+ { 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
+ 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }
+};
+
+static const vector unsigned char inv_shift_round = {
+ 0x00, 0x0d, 0x0a, 0x07,
+ 0x04, 0x01, 0x0e, 0x0B,
+ 0x08, 0x05, 0x02, 0x0f,
+ 0x0c, 0x09, 0x06, 0x03
+};
+
+static const vector unsigned char inv_select_0e_shifted = {
+ 0x00, 0x0d, 0x0a, 0x07,
+ 0x04, 0x01, 0x0e, 0x0B,
+ 0x08, 0x05, 0x02, 0x0f,
+ 0x0c, 0x09, 0x06, 0x03
+};
+
+static const vector unsigned char inv_select_0b_shifted = {
+ 0x0d, 0x0a, 0x07, 0x00,
+ 0x01, 0x0e, 0x0b, 0x04,
+ 0x05, 0x02, 0x0f, 0x08,
+ 0x09, 0x06, 0x03, 0x0c
+};
+
+static const vector unsigned char inv_select_0d_shifted = {
+ 0x0a, 0x07, 0x00, 0x0d,
+ 0x0e, 0x0b, 0x04, 0x01,
+ 0x02, 0x0f, 0x08, 0x05,
+ 0x06, 0x03, 0x0c, 0x09
+};
+
+static const vector unsigned char inv_select_09_shifted = {
+ 0x07, 0x00, 0x0d, 0x0a,
+ 0x0b, 0x04, 0x01, 0x0e,
+ 0x0f, 0x08, 0x05, 0x02,
+ 0x03, 0x0c, 0x09, 0x06
+};
+
+static const vector unsigned char inv_select_0e_norm = {
+ 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f
+};
+
+static const vector unsigned char inv_select_0b_norm = {
+ 0x01, 0x02, 0x03, 0x00,
+ 0x05, 0x06, 0x07, 0x04,
+ 0x09, 0x0a, 0x0b, 0x08,
+ 0x0d, 0x0e, 0x0f, 0x0c
+};
+
+static const vector unsigned char inv_select_0d_norm = {
+ 0x02, 0x03, 0x00, 0x01,
+ 0x06, 0x07, 0x04, 0x05,
+ 0x0a, 0x0b, 0x08, 0x09,
+ 0x0e, 0x0f, 0x0c, 0x0d
+};
+
+static const vector unsigned char inv_select_09_norm = {
+ 0x03, 0x00, 0x01, 0x02,
+ 0x07, 0x04, 0x05, 0x06,
+ 0x0b, 0x08, 0x09, 0x0a,
+ 0x0f, 0x0c, 0x0d, 0x0e
+};
+
+#ifdef CONFIG_CRYPTO_AES_ALTIVEC_TABLE
+/* small GF lookup table */
+static const vector unsigned char gf_mul_9_high = {
+ 0x00, 0x90, 0x3b, 0xab, 0x76, 0xe6, 0x4d, 0xdd,
+ 0xec, 0x7c, 0xd7, 0x47, 0x9a, 0x0a, 0xa1, 0x31
+};
+static const vector unsigned char gf_mul_b_high = {
+ 0x00, 0xb0, 0x7b, 0xcb, 0xf6, 0x46, 0x8d, 0x3d,
+ 0xf7, 0x47, 0x8c, 0x3c, 0x01, 0xb1, 0x7a, 0xca
+};
+static const vector unsigned char gf_mul_d_high = {
+ 0x00, 0xd0, 0xbb, 0x6b, 0x6d, 0xbd, 0xd6, 0x06,
+ 0xda, 0x0a, 0x61, 0xb1, 0xb7, 0x67, 0x0c, 0xdc
+};
+static const vector unsigned char gf_mul_e_high = {
+ 0x00, 0xe0, 0xdb, 0x3b, 0xad, 0x4d, 0x76, 0x96,
+ 0x41, 0xa1, 0x9a, 0x7a, 0xec, 0x0c, 0x37, 0xd7
+};
+static const vector unsigned char gf_mul_9_low = {
+ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+ 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77
+};
+static const vector unsigned char gf_mul_b_low = {
+ 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31,
+ 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69
+};
+static const vector unsigned char gf_mul_d_low = {
+ 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23,
+ 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b
+};
+static const vector unsigned char gf_mul_e_low = {
+ 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a,
+ 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a
+};
+#endif
+/* encryption code */
+
+static vector unsigned char ByteSub(vector unsigned char state)
+{
+ /* line of the s-box */
+ vector unsigned char line_01, line_23, line_45, line_67,
+ line_89, line_AB, line_CD, line_EF;
+ /* selector */
+ vector unsigned char sel1, sel2, sel7;
+ /* correct lines */
+ vector unsigned char cor_0123, cor_4567, cor_89AB, cor_CDEF,
+ cor_0to7, cor_8toF;
+ vector unsigned char ret_state;
+ vector unsigned char state_shift2, state_shift1;
+
+ line_01 = vec_perm(sbox_enc[0], sbox_enc[1], state);
+ line_23 = vec_perm(sbox_enc[2], sbox_enc[3], state);
+ line_45 = vec_perm(sbox_enc[4], sbox_enc[5], state);
+ line_67 = vec_perm(sbox_enc[6], sbox_enc[7], state);
+ line_89 = vec_perm(sbox_enc[8], sbox_enc[9], state);
+ line_AB = vec_perm(sbox_enc[10], sbox_enc[11], state);
+ line_CD = vec_perm(sbox_enc[12], sbox_enc[13], state);
+ line_EF = vec_perm(sbox_enc[14], sbox_enc[15], state);
+
+ state_shift2 = vec_vslb(state, vec_splat_u8(2));
+ sel2 = (typeof (sel2)) vec_vcmpgtub(state_shift2, imm_7Fh);
+ cor_0123 = vec_sel(line_01, line_23, sel2);
+ cor_4567 = vec_sel(line_45, line_67, sel2);
+ cor_89AB = vec_sel(line_89, line_AB, sel2);
+ cor_CDEF = vec_sel(line_CD, line_EF, sel2);
+
+ state_shift1 = vec_vslb(state, vec_splat_u8(1));
+ sel1 = (typeof (sel1))vec_vcmpgtub(state_shift1, imm_7Fh);
+ cor_0to7 = vec_sel(cor_0123, cor_4567, sel1);
+ cor_8toF = vec_sel(cor_89AB, cor_CDEF, sel1);
+
+ sel7 = (typeof (sel7))vec_vcmpgtub(state, imm_7Fh);
+ ret_state = vec_sel(cor_0to7, cor_8toF, sel7);
+
+ return ret_state;
+}
+
+static vector unsigned char ShiftRow(vector unsigned char state)
+{
+
+ return vec_perm(state, state, shift_round);
+}
+
+static vector unsigned char MixColumn(vector unsigned char state)
+{
+ vector unsigned char imm_00h, imm_01h;
+ vector unsigned char need_add;
+ vector unsigned char shifted_vec, modul;
+ vector unsigned char toadd, xtimed;
+ vector unsigned char op1, op2, op3, op4, op5;
+ vector unsigned char xor_12, xor_34, xor_1234, ret;
+
+ imm_00h = vec_splat_u8(0x00);
+ imm_01h = vec_splat_u8(0x01);
+
+ modul = vec_splat( vec_lvsr(0, (unsigned char *) 0), 0x0b); // 0x1b
+
+ need_add = (vector unsigned char)vec_vcmpgtub(state, imm_7Fh);
+ shifted_vec = vec_vslb(state, imm_01h);
+
+ toadd = vec_sel(imm_00h, modul, need_add);
+
+ xtimed = vec_xor(toadd, shifted_vec);
+
+ op1 = vec_perm(state, xtimed, pre_xor_s0);
+ op2 = vec_perm(state, xtimed, pre_xor_s1);
+ op3 = vec_perm(state, xtimed, pre_xor_s2);
+ op4 = vec_perm(state, xtimed, pre_xor_s3);
+ op5 = vec_perm(state, xtimed, pre_xor_s4);
+
+ xor_12 = vec_xor(op1, op2);
+ xor_34 = vec_xor(op3, op4);
+ xor_1234 = vec_xor(xor_12, xor_34);
+ ret = vec_xor(xor_1234, op5);
+
+ return ret;
+}
+
+static vector unsigned char AddRoundKey(vector unsigned char state,
+ vector unsigned char key)
+{
+ return vec_xor(state,key);
+}
+
+static vector unsigned char normalRound(vector unsigned char state, vector unsigned char key)
+{
+ vector unsigned char pstate;
+
+ pstate = ByteSub(state);
+ pstate = MixColumn(pstate);
+ pstate = AddRoundKey(pstate, key);
+ return pstate;
+}
+
+static vector unsigned char finalRound(vector unsigned char state, vector unsigned char key)
+{
+ vector unsigned char pstate;
+
+ pstate = ByteSub(state);
+ pstate = ShiftRow(pstate);
+ pstate = AddRoundKey(pstate, key);
+ return pstate;
+}
+
+static vector unsigned char _aes_encrypt_altivec(vector unsigned char in,
+ const vector unsigned char *key, unsigned char key_len)
+{
+ unsigned char i;
+ vector unsigned char pstate;
+
+ pstate = vec_xor(in, *key++);
+ switch (key_len) {
+
+ case 32: /* 14 rounds */
+ pstate = normalRound(pstate, *key++);
+ pstate = normalRound(pstate, *key++);
+
+ case 24: /* 12 rounds */
+ pstate = normalRound(pstate, *key++);
+ pstate = normalRound(pstate, *key++);
+
+ case 16: /* 10 rounds */
+ for (i=0; i<9; i++)
+ pstate = normalRound(pstate, *key++);
+
+ break;
+
+ default:
+ /* unsupported */
+ BUG();
+ }
+
+ pstate = finalRound(pstate, *key);
+ return pstate;
+}
+
+int aes_encrypt_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len)
+{
+ vector unsigned char pstate;
+
+ pstate = vec_ld(0, in);
+ pstate = _aes_encrypt_altivec(pstate, (const vector unsigned char*) kp, key_len);
+
+ vec_st(pstate, 0, out);
+ return 0;
+}
+/* decryption code, alternative version */
+
+static vector unsigned char InvByteSub(vector unsigned char state)
+{
+ /* line of the s-box */
+ vector unsigned char line_01, line_23, line_45, line_67,
+ line_89, line_AB, line_CD, line_EF;
+ /* selector */
+ vector unsigned char sel1, sel2, sel7;
+ /* correct lines */
+ vector unsigned char cor_0123, cor_4567, cor_89AB, cor_CDEF,
+ cor_0to7, cor_8toF;
+ vector unsigned char ret_state;
+ vector unsigned char state_shift2, state_shift1;
+
+ line_01 = vec_perm(sbox_dec[0], sbox_dec[1], state);
+ line_23 = vec_perm(sbox_dec[2], sbox_dec[3], state);
+ line_45 = vec_perm(sbox_dec[4], sbox_dec[5], state);
+ line_67 = vec_perm(sbox_dec[6], sbox_dec[7], state);
+ line_89 = vec_perm(sbox_dec[8], sbox_dec[9], state);
+ line_AB = vec_perm(sbox_dec[10], sbox_dec[11], state);
+ line_CD = vec_perm(sbox_dec[12], sbox_dec[13], state);
+ line_EF = vec_perm(sbox_dec[14], sbox_dec[15], state);
+
+ state_shift2 = vec_vslb(state, vec_splat_u8(2));
+ sel2 = (typeof (sel2)) vec_vcmpgtub(state_shift2, imm_7Fh);
+ cor_0123 = vec_sel(line_01, line_23, sel2);
+ cor_4567 = vec_sel(line_45, line_67, sel2);
+ cor_89AB = vec_sel(line_89, line_AB, sel2);
+ cor_CDEF = vec_sel(line_CD, line_EF, sel2);
+
+ state_shift1 = vec_vslb(state, vec_splat_u8(1));
+ sel1 = (typeof (sel1))vec_vcmpgtub(state_shift1, imm_7Fh);
+ cor_0to7 = vec_sel(cor_0123, cor_4567, sel1);
+ cor_8toF = vec_sel(cor_89AB, cor_CDEF, sel1);
+
+ sel7 = (typeof (sel7))vec_vcmpgtub(state, imm_7Fh);
+ ret_state = vec_sel(cor_0to7, cor_8toF, sel7);
+
+ return ret_state;
+}
+
+static vector unsigned char InvShiftRow(vector unsigned char state)
+{
+
+ return vec_perm(state, state, inv_shift_round);
+}
+
+static vector unsigned char InvMixColumn(vector unsigned char state,
+ vector unsigned char inv_select_0e, vector unsigned char inv_select_0b,
+ vector unsigned char inv_select_0d, vector unsigned char inv_select_09 )
+{
+ vector unsigned char op0, op1, op2, op3, op4, op5;
+ vector unsigned char mul_0e, mul_09, mul_0d, mul_0b;
+ vector unsigned char ret;
+
+#ifdef CONFIG_CRYPTO_AES_ALTIVEC_TABLE
+ /* 14 operations, 1x 8 memory loads */
+
+ vector unsigned char state_high;
+ vector unsigned char imm_04h;
+ vector unsigned char mul_09_hi, mul_09_lo, mul_0b_hi, mul_0b_lo, mul_0d_hi,
+ mul_0d_lo, mul_0e_hi, mul_0e_lo;
+
+ imm_04h = vec_splat_u8(0x04);
+
+ state_high = vec_sr(state, imm_04h);
+
+ mul_09_hi = vec_perm(gf_mul_9_high, gf_mul_9_high, state_high);
+ mul_0b_hi = vec_perm(gf_mul_b_high, gf_mul_b_high, state_high);
+ mul_0d_hi = vec_perm(gf_mul_d_high, gf_mul_d_high, state_high);
+ mul_0e_hi = vec_perm(gf_mul_e_high, gf_mul_e_high, state_high);
+
+ mul_09_lo = vec_perm(gf_mul_9_low, gf_mul_9_low, state);
+ mul_0b_lo = vec_perm(gf_mul_b_low, gf_mul_b_low, state);
+ mul_0d_lo = vec_perm(gf_mul_d_low, gf_mul_d_low, state);
+ mul_0e_lo = vec_perm(gf_mul_e_low, gf_mul_e_low, state);
+
+ mul_09 = vec_xor(mul_09_hi, mul_09_lo);
+ mul_0b = vec_xor(mul_0b_hi, mul_0b_lo);
+ mul_0d = vec_xor(mul_0d_hi, mul_0d_lo);
+ mul_0e = vec_xor(mul_0e_hi, mul_0e_lo);
+
+#else
+ /* 21 operations, 3x 1 memory loads */
+
+ vector unsigned char imm_00h, imm_01h;
+ vector unsigned char need_add;
+ vector unsigned char shifted_vec, modul;
+ vector unsigned char toadd;
+ vector unsigned char mul_2, mul_4, mul_8;
+ vector unsigned char mul_2_4;
+
+ /* compute 0e, 0b, 0d, 09 in GF */
+ imm_00h = vec_splat_u8(0x00);
+ imm_01h = vec_splat_u8(0x01);
+
+ modul = vec_splat( vec_lvsr(0, (unsigned char *) 0), 0x0b); // 0x1b
+
+ need_add = (vector unsigned char)vec_vcmpgtub(state, imm_7Fh);
+ shifted_vec = vec_vslb(state, imm_01h);
+ toadd = vec_sel(imm_00h, modul, need_add);
+ mul_2 = vec_xor(toadd, shifted_vec);
+
+ need_add = (vector unsigned char)vec_vcmpgtub(mul_2, imm_7Fh);
+ shifted_vec = vec_vslb(mul_2, imm_01h);
+ toadd = vec_sel(imm_00h, modul, need_add);
+ mul_4 = vec_xor(toadd, shifted_vec);
+
+ need_add = (vector unsigned char)vec_vcmpgtub(mul_4, imm_7Fh);
+ shifted_vec = vec_vslb(mul_4, imm_01h);
+ toadd = vec_sel(imm_00h, modul, need_add);
+ mul_8 = vec_xor(toadd, shifted_vec);
+
+ mul_2_4 = vec_xor(mul_2, mul_4);
+ /* 09 = 8 * 1 */
+ mul_09 = vec_xor(mul_8, state);
+
+ /* 0e = 2 * 4 * 8 */
+ mul_0e = vec_xor(mul_2_4, mul_8);
+
+ /* 0b = 2 * 8 * 1 */
+ mul_0b = vec_xor(mul_2, mul_09);
+
+ /* 0d = 4 * 8 * 1 */
+ mul_0d = vec_xor(mul_4, mul_09);
+#endif
+
+ /* prepare vectors for add */
+
+ op0 = vec_perm(mul_0e, mul_0e, inv_select_0e);
+ op1 = vec_perm(mul_0b, mul_0b, inv_select_0b);
+ op2 = vec_perm(mul_0d, mul_0d, inv_select_0d);
+ op3 = vec_perm(mul_09, mul_09, inv_select_09);
+
+ op4 = vec_xor(op0, op1);
+ op5 = vec_xor(op2, op3);
+ ret = vec_xor(op4, op5);
+ return ret;
+}
+
+static vector unsigned char InvNormalRound(vector unsigned char state,
+ vector unsigned char key)
+{
+ vector unsigned char pstate;
+
+ pstate = InvByteSub(state);
+ pstate = InvMixColumn(pstate, inv_select_0e_shifted, inv_select_0b_shifted,
+ inv_select_0d_shifted, inv_select_09_shifted);
+ pstate = AddRoundKey(pstate, key);
+ return pstate;
+}
+
+static vector unsigned char InvfinalRound(vector unsigned char state,
+ vector unsigned char key)
+{
+ vector unsigned char pstate;
+
+ pstate = InvByteSub(state);
+ pstate = InvShiftRow(pstate);
+ pstate = AddRoundKey(pstate, key);
+ return pstate;
+}
+
+
+static vector unsigned char _aes_decrypt_altivec(vector unsigned char in,
+ vector const unsigned char *key, unsigned int key_len)
+{
+ vector unsigned char pstate;
+ unsigned int i;
+
+ pstate = vec_xor(in, *key++);
+
+ switch (key_len) {
+ case 32: /* 14 rounds */
+ pstate = InvNormalRound(pstate, *key++);
+ pstate = InvNormalRound(pstate, *key++);
+
+ case 24: /* 12 rounds */
+ pstate = InvNormalRound(pstate, *key++);
+ pstate = InvNormalRound(pstate, *key++);
+
+ case 16: /* 10 rounds */
+ for (i=0; i<9; i++)
+ pstate = InvNormalRound(pstate, *key++);
+
+ break;
+
+ default:
+ BUG();
+ }
+
+ pstate = InvfinalRound(pstate, *key);
+ return pstate;
+}
+
+int aes_decrypt_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len)
+{
+ vector unsigned char pstate;
+
+ pstate = vec_ld(0, in);
+ pstate = _aes_decrypt_altivec(pstate, (const vector unsigned char*) kp, key_len);
+ vec_st(pstate, 0, out);
+ return 0;
+}
+
+/* expand key */
+
+static unsigned int SubWord(unsigned int in)
+{
+ unsigned char buff[16] __attribute__ ((aligned (16)));
+ vector unsigned char vec_buf;
+
+ buff[0] = in >> 24;
+ buff[1] = (in >> 16) & 0xff;
+ buff[2] = (in >> 8) & 0xff;
+ buff[3] = in & 0xff;
+
+ vec_buf = vec_ld(0, buff);
+ vec_buf = ByteSub(vec_buf);
+ vec_st(vec_buf, 0, buff);
+ return buff[0] << 24 | buff[1] << 16 | buff[2] << 8 | buff[3];
+}
+
+static unsigned int RotWord(unsigned int word)
+{
+ return (word << 8 | word >> 24);
+}
+
+int expand_key(const unsigned char *key, unsigned int keylen,
+ unsigned char exp_enc_key[15 *4*4], unsigned char exp_dec_key[15*4*4])
+{
+ unsigned int tmp, i, rounds;
+ unsigned int expanded_key[15 *4] __attribute__ ((aligned (16)));
+ vector unsigned char expanded_dec_key[15];
+ vector unsigned char mixed_key;
+ vector unsigned char *cur_key;
+
+ switch (keylen) {
+ case 4:
+ rounds = 10;
+ break;
+
+ case 6:
+ rounds = 12;
+ break;
+
+ case 8:
+ rounds = 14;
+ break;
+
+ default:
+ /* wrong key size */
+ return -EINVAL;
+ }
+
+ memcpy(expanded_key, key, keylen*4);
+
+ i = keylen;
+
+ /* setup enc key */
+
+ for (; i< 4 * (rounds+1); i++) {
+ tmp = expanded_key[i-1];
+
+ if (!(i % keylen)) {
+ tmp = RotWord(tmp);
+ tmp = SubWord(tmp);
+ tmp ^= Rcon[i / keylen ];
+ } else if (keylen > 6 && (i % keylen == 4))
+ tmp = SubWord(tmp);
+
+ expanded_key[i] = expanded_key[i-keylen] ^ tmp;
+ }
+
+ memcpy(exp_enc_key, expanded_key, 15*4*4);
+
+ /* setup dec key: the key is turned arround and prepared for the
+ * "alternative decryption" mode
+ */
+
+ cur_key = (vector unsigned char*) expanded_key;
+
+ memcpy(&expanded_dec_key[rounds], &expanded_key[0], 4*4);
+ memcpy(&expanded_dec_key[0], &expanded_key[rounds *4], 4*4);
+
+ cur_key++;
+ for (i = (rounds-1); i> 0; i--) {
+
+ mixed_key = InvMixColumn(*cur_key++, inv_select_0e_norm, inv_select_0b_norm,
+ inv_select_0d_norm, inv_select_09_norm);
+ expanded_dec_key[i] = mixed_key;
+ }
+
+ memcpy(exp_dec_key, expanded_dec_key, 15*4*4);
+ return 0;
+}
+
+int aes_encrypt_ecb_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len, unsigned int len,
+ unsigned char *iv_)
+{
+ unsigned int left = len;
+
+ while (left >= 32) {
+ aes_encrypt_altivec(in, out, kp, key_len);
+ aes_encrypt_altivec(in+16, out+16, kp, key_len);
+ left -= 32;
+ in += 32;
+ out += 32;
+ }
+
+ while (left >= 16) {
+ aes_encrypt_altivec(in, out, kp, key_len);
+ left -= 16;
+ in += 16;
+ out += 16;
+ }
+
+ return len;
+}
+
+int aes_decrypt_ecb_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len, unsigned int len,
+ unsigned char *iv_)
+{
+ unsigned int left = len;
+
+ while (left >= 32) {
+ aes_decrypt_altivec(in, out, kp, key_len);
+ aes_decrypt_altivec(in+16, out+16, kp, key_len);
+ left -= 32;
+ in += 32;
+ out += 32;
+ }
+
+ while (left >= 16) {
+ aes_decrypt_altivec(in, out, kp, key_len);
+ left -= 16;
+ in += 16;
+ out += 16;
+ }
+ return len;
+}
+
+int aes_encrypt_cbc_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len, unsigned int len,
+ unsigned char *iv_)
+{
+ unsigned int i;
+ vector unsigned char iv, input;
+
+ iv = vec_ld(0, iv_);
+ for (i=0; i< len; i += 16) {
+ input = vec_ld(0, in);
+ input = vec_xor(input, iv);
+
+ iv = _aes_encrypt_altivec(input, (const vector unsigned char*) kp, key_len);
+
+ vec_st(iv, 0, out);
+
+ in += 16;
+ out += 16;
+ }
+
+ vec_st(iv, 0, iv_);
+ return len;
+}
+
+int aes_decrypt_cbc_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len, unsigned int len,
+ unsigned char *iv_)
+{
+ unsigned int i;
+ vector unsigned char iv, input, vret, decrypted;
+
+ iv = vec_ld(0, iv_);
+ for (i=0; i< len; i += 16) {
+
+ input = vec_ld(0, in);
+ vret = _aes_decrypt_altivec(input, (const vector unsigned char*) kp, key_len);
+
+ decrypted = vec_xor(vret, iv);
+ iv = input;
+
+ vec_st(decrypted, 0, out);
+
+ in += 16;
+ out += 16;
+ }
+
+ vec_st(iv, 0, iv_);
+ return len;
+}
Index: linux/crypto/aes-altivec.h
===================================================================
--- /dev/null
+++ linux/crypto/aes-altivec.h
@@ -0,0 +1,28 @@
+#ifndef __AES_ALTIVEC_H__
+#define __AES_ALTIVEC_H__
+
+extern int expand_key(const unsigned char *key, unsigned int keylen,
+ unsigned char exp_enc_key[15 *4*4], unsigned char expanded_dec_key[15*4*4]);
+
+extern int aes_encrypt_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len);
+
+extern int aes_decrypt_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len);
+
+extern int aes_encrypt_ecb_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len, unsigned int len,
+ unsigned char *iv_);
+
+extern int aes_decrypt_ecb_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len, unsigned int len,
+ unsigned char *iv_);
+
+extern int aes_encrypt_cbc_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len, unsigned int len,
+ unsigned char *iv_);
+
+extern int aes_decrypt_cbc_altivec(const unsigned char *in, unsigned char *out,
+ const unsigned char *kp, unsigned int key_len, unsigned int len,
+ unsigned char *iv_);
+#endif
Index: linux/crypto/Kconfig
===================================================================
--- linux.orig/crypto/Kconfig
+++ linux/crypto/Kconfig
@@ -325,6 +325,21 @@ config CRYPTO_AES_X86_64
See <http://csrc.nist.gov/encryption/aes/> for more information.
+config CRYPTO_AES_ALTIVEC
+ tristate "AES with AltiVec support"
+ select CRYPTO_ALGAPI
+ depends on ALTIVEC
+ help
+ AES cipher algorithms (FIPS-197). AES uses the Rijndael
+ algorithm. This implementation has AltiVec support.
+
+config CRYPTO_AES_ALTIVEC_TABLE
+ bool "Use table lookup for decryption"
+ depends on CRYPTO_AES_ALTIVEC
+ help
+ Use precomputed tables for decryption instead of computing
+ "by hand" in GF. This solution is slower.
+
config CRYPTO_CAST5
tristate "CAST5 (CAST-128) cipher algorithm"
select CRYPTO_ALGAPI
Index: linux/crypto/Makefile
===================================================================
--- linux.orig/crypto/Makefile
+++ linux/crypto/Makefile
@@ -48,3 +48,7 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += mich
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
+
+CFLAGS_aes-altivec.o += -O3 -maltivec
+aes_altivec-objs := aes-alti.o aes-altivec.o
+obj-$(CONFIG_CRYPTO_AES_ALTIVEC) += aes_altivec.o
--
^ 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