aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Jarzmik <rjarzmik@free.fr>2008-05-02 16:17:06 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-05-04 06:06:05 -0400
commit649de51b883746d76c5fa1614dd067054c9d702a (patch)
tree68c3b172063bdf4cc82a727d3d4ca48f63487665
parentc8df9a53e8d16877fc0b268b002af2a47a14643a (diff)
[ARM] 5027/1: Fixed random memory corruption on pxa suspend cycle.
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>
-rw-r--r--arch/arm/mach-pxa/pm.c7
-rw-r--r--arch/arm/mach-pxa/pxa25x.c8
-rw-r--r--arch/arm/mach-pxa/pxa27x.c8
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c7
-rw-r--r--arch/arm/mach-sa1100/pm.c8
-rw-r--r--include/asm-arm/arch-pxa/pm.h2
6 files changed, 17 insertions, 23 deletions
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index ec1bbf333a3a..329df2152dcd 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -42,7 +42,7 @@ int pxa_pm_enter(suspend_state_t state)
42 if (state != PM_SUSPEND_STANDBY) { 42 if (state != PM_SUSPEND_STANDBY) {
43 pxa_cpu_pm_fns->save(sleep_save); 43 pxa_cpu_pm_fns->save(sleep_save);
44 /* before sleeping, calculate and save a checksum */ 44 /* before sleeping, calculate and save a checksum */
45 for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++) 45 for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++)
46 sleep_save_checksum += sleep_save[i]; 46 sleep_save_checksum += sleep_save[i];
47 } 47 }
48 48
@@ -55,7 +55,7 @@ int pxa_pm_enter(suspend_state_t state)
55 55
56 if (state != PM_SUSPEND_STANDBY) { 56 if (state != PM_SUSPEND_STANDBY) {
57 /* after sleeping, validate the checksum */ 57 /* after sleeping, validate the checksum */
58 for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++) 58 for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++)
59 checksum += sleep_save[i]; 59 checksum += sleep_save[i];
60 60
61 /* if invalid, display message and wait for a hardware reset */ 61 /* if invalid, display message and wait for a hardware reset */
@@ -101,7 +101,8 @@ static int __init pxa_pm_init(void)
101 return -EINVAL; 101 return -EINVAL;
102 } 102 }
103 103
104 sleep_save = kmalloc(pxa_cpu_pm_fns->save_size, GFP_KERNEL); 104 sleep_save = kmalloc(pxa_cpu_pm_fns->save_count * sizeof(unsigned long),
105 GFP_KERNEL);
105 if (!sleep_save) { 106 if (!sleep_save) {
106 printk(KERN_ERR "failed to alloc memory for pm save\n"); 107 printk(KERN_ERR "failed to alloc memory for pm save\n");
107 return -ENOMEM; 108 return -ENOMEM;
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index d9b5450aee5b..3642f81f8f0e 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -150,9 +150,7 @@ static struct clk pxa25x_clks[] = {
150 * More ones like CP and general purpose register values are preserved 150 * More ones like CP and general purpose register values are preserved
151 * with the stack pointer in sleep.S. 151 * with the stack pointer in sleep.S.
152 */ 152 */
153enum { SLEEP_SAVE_START = 0, 153enum { SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2,
154
155 SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2,
156 154
157 SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, 155 SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
158 SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U, 156 SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
@@ -162,7 +160,7 @@ enum { SLEEP_SAVE_START = 0,
162 160
163 SLEEP_SAVE_CKEN, 161 SLEEP_SAVE_CKEN,
164 162
165 SLEEP_SAVE_SIZE 163 SLEEP_SAVE_COUNT
166}; 164};
167 165
168 166
@@ -210,7 +208,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)
210} 208}
211 209
212static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = { 210static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = {
213 .save_size = SLEEP_SAVE_SIZE, 211 .save_count = SLEEP_SAVE_COUNT,
214 .valid = suspend_valid_only_mem, 212 .valid = suspend_valid_only_mem,
215 .save = pxa25x_cpu_pm_save, 213 .save = pxa25x_cpu_pm_save,
216 .restore = pxa25x_cpu_pm_restore, 214 .restore = pxa25x_cpu_pm_restore,
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 7a2449dd0fd4..505dccaa51f5 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -181,9 +181,7 @@ static struct clk pxa27x_clks[] = {
181 * More ones like CP and general purpose register values are preserved 181 * More ones like CP and general purpose register values are preserved
182 * with the stack pointer in sleep.S. 182 * with the stack pointer in sleep.S.
183 */ 183 */
184enum { SLEEP_SAVE_START = 0, 184enum { SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
185
186 SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
187 185
188 SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, 186 SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
189 SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U, 187 SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
@@ -198,7 +196,7 @@ enum { SLEEP_SAVE_START = 0,
198 SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER, 196 SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER,
199 SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR, 197 SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR,
200 198
201 SLEEP_SAVE_SIZE 199 SLEEP_SAVE_COUNT
202}; 200};
203 201
204void pxa27x_cpu_pm_save(unsigned long *sleep_save) 202void pxa27x_cpu_pm_save(unsigned long *sleep_save)
@@ -269,7 +267,7 @@ static int pxa27x_cpu_pm_valid(suspend_state_t state)
269} 267}
270 268
271static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = { 269static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = {
272 .save_size = SLEEP_SAVE_SIZE, 270 .save_count = SLEEP_SAVE_COUNT,
273 .save = pxa27x_cpu_pm_save, 271 .save = pxa27x_cpu_pm_save,
274 .restore = pxa27x_cpu_pm_restore, 272 .restore = pxa27x_cpu_pm_restore,
275 .valid = pxa27x_cpu_pm_valid, 273 .valid = pxa27x_cpu_pm_valid,
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index b6a6f5fcc77a..644550bfa330 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -256,12 +256,11 @@ static unsigned long wakeup_src;
256#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x 256#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
257#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] 257#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
258 258
259enum { SLEEP_SAVE_START = 0, 259enum { SLEEP_SAVE_CKENA,
260 SLEEP_SAVE_CKENA,
261 SLEEP_SAVE_CKENB, 260 SLEEP_SAVE_CKENB,
262 SLEEP_SAVE_ACCR, 261 SLEEP_SAVE_ACCR,
263 262
264 SLEEP_SAVE_SIZE, 263 SLEEP_SAVE_COUNT,
265}; 264};
266 265
267static void pxa3xx_cpu_pm_save(unsigned long *sleep_save) 266static void pxa3xx_cpu_pm_save(unsigned long *sleep_save)
@@ -376,7 +375,7 @@ static int pxa3xx_cpu_pm_valid(suspend_state_t state)
376} 375}
377 376
378static struct pxa_cpu_pm_fns pxa3xx_cpu_pm_fns = { 377static struct pxa_cpu_pm_fns pxa3xx_cpu_pm_fns = {
379 .save_size = SLEEP_SAVE_SIZE, 378 .save_count = SLEEP_SAVE_COUNT,
380 .save = pxa3xx_cpu_pm_save, 379 .save = pxa3xx_cpu_pm_save,
381 .restore = pxa3xx_cpu_pm_restore, 380 .restore = pxa3xx_cpu_pm_restore,
382 .valid = pxa3xx_cpu_pm_valid, 381 .valid = pxa3xx_cpu_pm_valid,
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index 246c573e7252..1693d447a224 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -43,20 +43,18 @@ extern void sa1100_cpu_resume(void);
43 * More ones like CP and general purpose register values are preserved 43 * More ones like CP and general purpose register values are preserved
44 * on the stack and then the stack pointer is stored last in sleep.S. 44 * on the stack and then the stack pointer is stored last in sleep.S.
45 */ 45 */
46enum { SLEEP_SAVE_SP = 0, 46enum { SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
47
48 SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
49 SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR, 47 SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
50 48
51 SLEEP_SAVE_Ser1SDCR0, 49 SLEEP_SAVE_Ser1SDCR0,
52 50
53 SLEEP_SAVE_SIZE 51 SLEEP_SAVE_COUNT
54}; 52};
55 53
56 54
57static int sa11x0_pm_enter(suspend_state_t state) 55static int sa11x0_pm_enter(suspend_state_t state)
58{ 56{
59 unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE]; 57 unsigned long gpio, sleep_save[SLEEP_SAVE_COUNT];
60 58
61 gpio = GPLR; 59 gpio = GPLR;
62 60
diff --git a/include/asm-arm/arch-pxa/pm.h b/include/asm-arm/arch-pxa/pm.h
index 9d9f4b54b2ce..261e5bc958db 100644
--- a/include/asm-arm/arch-pxa/pm.h
+++ b/include/asm-arm/arch-pxa/pm.h
@@ -10,7 +10,7 @@
10#include <linux/suspend.h> 10#include <linux/suspend.h>
11 11
12struct pxa_cpu_pm_fns { 12struct pxa_cpu_pm_fns {
13 int save_size; 13 int save_count;
14 void (*save)(unsigned long *); 14 void (*save)(unsigned long *);
15 void (*restore)(unsigned long *); 15 void (*restore)(unsigned long *);
16 int (*valid)(suspend_state_t state); 16 int (*valid)(suspend_state_t state);