[ARM] 5027/1: Fixed random memory corruption on pxa suspend cycle.
authorRobert Jarzmik <rjarzmik@free.fr>
Fri, 2 May 2008 20:17:06 +0000 (21:17 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 4 May 2008 10:06:05 +0000 (11:06 +0100)
Each time a pxa type cpu went in suspend, a portion of
kmalloc memory was corrupted.
The issue was an incorrect length allocation introduced by
the commit 711be5ccfe9a02ba560aa918a008c31ea4760163 for
the save registers array (=> overflow).

Signed-off-by: Robert Jarzmik <rjarzmik@free.fr>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mach-pxa/pm.c
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-sa1100/pm.c
include/asm-arm/arch-pxa/pm.h

index ec1bbf3..329df21 100644 (file)
@@ -42,7 +42,7 @@ int pxa_pm_enter(suspend_state_t state)
        if (state != PM_SUSPEND_STANDBY) {
                pxa_cpu_pm_fns->save(sleep_save);
                /* before sleeping, calculate and save a checksum */
-               for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++)
+               for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++)
                        sleep_save_checksum += sleep_save[i];
        }
 
@@ -55,7 +55,7 @@ int pxa_pm_enter(suspend_state_t state)
 
        if (state != PM_SUSPEND_STANDBY) {
                /* after sleeping, validate the checksum */
-               for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++)
+               for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++)
                        checksum += sleep_save[i];
 
                /* if invalid, display message and wait for a hardware reset */
@@ -101,7 +101,8 @@ static int __init pxa_pm_init(void)
                return -EINVAL;
        }
 
-       sleep_save = kmalloc(pxa_cpu_pm_fns->save_size, GFP_KERNEL);
+       sleep_save = kmalloc(pxa_cpu_pm_fns->save_count * sizeof(unsigned long),
+                            GFP_KERNEL);
        if (!sleep_save) {
                printk(KERN_ERR "failed to alloc memory for pm save\n");
                return -ENOMEM;
index d9b5450..3642f81 100644 (file)
@@ -150,9 +150,7 @@ static struct clk pxa25x_clks[] = {
  * More ones like CP and general purpose register values are preserved
  * with the stack pointer in sleep.S.
  */
-enum { SLEEP_SAVE_START = 0,
-
-       SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2,
+enum { SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2,
 
        SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
        SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
@@ -162,7 +160,7 @@ enum {      SLEEP_SAVE_START = 0,
 
        SLEEP_SAVE_CKEN,
 
-       SLEEP_SAVE_SIZE
+       SLEEP_SAVE_COUNT
 };
 
 
@@ -210,7 +208,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)
 }
 
 static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = {
-       .save_size      = SLEEP_SAVE_SIZE,
+       .save_count     = SLEEP_SAVE_COUNT,
        .valid          = suspend_valid_only_mem,
        .save           = pxa25x_cpu_pm_save,
        .restore        = pxa25x_cpu_pm_restore,
index 7a2449d..505dcca 100644 (file)
@@ -181,9 +181,7 @@ static struct clk pxa27x_clks[] = {
  * More ones like CP and general purpose register values are preserved
  * with the stack pointer in sleep.S.
  */
-enum { SLEEP_SAVE_START = 0,
-
-       SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
+enum { SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
 
        SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
        SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
@@ -198,7 +196,7 @@ enum {      SLEEP_SAVE_START = 0,
        SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER,
        SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR,
 
-       SLEEP_SAVE_SIZE
+       SLEEP_SAVE_COUNT
 };
 
 void pxa27x_cpu_pm_save(unsigned long *sleep_save)
@@ -269,7 +267,7 @@ static int pxa27x_cpu_pm_valid(suspend_state_t state)
 }
 
 static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = {
-       .save_size      = SLEEP_SAVE_SIZE,
+       .save_count     = SLEEP_SAVE_COUNT,
        .save           = pxa27x_cpu_pm_save,
        .restore        = pxa27x_cpu_pm_restore,
        .valid          = pxa27x_cpu_pm_valid,
index b6a6f5f..644550b 100644 (file)
@@ -256,12 +256,11 @@ static unsigned long wakeup_src;
 #define SAVE(x)                sleep_save[SLEEP_SAVE_##x] = x
 #define RESTORE(x)     x = sleep_save[SLEEP_SAVE_##x]
 
-enum { SLEEP_SAVE_START = 0,
-       SLEEP_SAVE_CKENA,
+enum { SLEEP_SAVE_CKENA,
        SLEEP_SAVE_CKENB,
        SLEEP_SAVE_ACCR,
 
-       SLEEP_SAVE_SIZE,
+       SLEEP_SAVE_COUNT,
 };
 
 static void pxa3xx_cpu_pm_save(unsigned long *sleep_save)
@@ -376,7 +375,7 @@ static int pxa3xx_cpu_pm_valid(suspend_state_t state)
 }
 
 static struct pxa_cpu_pm_fns pxa3xx_cpu_pm_fns = {
-       .save_size      = SLEEP_SAVE_SIZE,
+       .save_count     = SLEEP_SAVE_COUNT,
        .save           = pxa3xx_cpu_pm_save,
        .restore        = pxa3xx_cpu_pm_restore,
        .valid          = pxa3xx_cpu_pm_valid,
index 246c573..1693d44 100644 (file)
@@ -43,20 +43,18 @@ extern void sa1100_cpu_resume(void);
  * More ones like CP and general purpose register values are preserved
  * on the stack and then the stack pointer is stored last in sleep.S.
  */
-enum { SLEEP_SAVE_SP = 0,
-
-       SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
+enum { SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
        SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
 
        SLEEP_SAVE_Ser1SDCR0,
 
-       SLEEP_SAVE_SIZE
+       SLEEP_SAVE_COUNT
 };
 
 
 static int sa11x0_pm_enter(suspend_state_t state)
 {
-       unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
+       unsigned long gpio, sleep_save[SLEEP_SAVE_COUNT];
 
        gpio = GPLR;
 
index 9d9f4b5..261e5bc 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/suspend.h>
 
 struct pxa_cpu_pm_fns {
-       int     save_size;
+       int     save_count;
        void    (*save)(unsigned long *);
        void    (*restore)(unsigned long *);
        int     (*valid)(suspend_state_t state);