diff options
author | Robert Jarzmik <rjarzmik@free.fr> | 2008-05-02 16:17:06 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-05-04 06:06:05 -0400 |
commit | 649de51b883746d76c5fa1614dd067054c9d702a (patch) | |
tree | 68c3b172063bdf4cc82a727d3d4ca48f63487665 | |
parent | c8df9a53e8d16877fc0b268b002af2a47a14643a (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.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa25x.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa3xx.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/pm.c | 8 | ||||
-rw-r--r-- | include/asm-arm/arch-pxa/pm.h | 2 |
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 | */ |
153 | enum { SLEEP_SAVE_START = 0, | 153 | enum { 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 | ||
212 | static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = { | 210 | static 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 | */ |
184 | enum { SLEEP_SAVE_START = 0, | 184 | enum { 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 | ||
204 | void pxa27x_cpu_pm_save(unsigned long *sleep_save) | 202 | void 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 | ||
271 | static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = { | 269 | static 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 | ||
259 | enum { SLEEP_SAVE_START = 0, | 259 | enum { 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 | ||
267 | static void pxa3xx_cpu_pm_save(unsigned long *sleep_save) | 266 | static 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 | ||
378 | static struct pxa_cpu_pm_fns pxa3xx_cpu_pm_fns = { | 377 | static 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 | */ |
46 | enum { SLEEP_SAVE_SP = 0, | 46 | enum { 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 | ||
57 | static int sa11x0_pm_enter(suspend_state_t state) | 55 | static 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 | ||
12 | struct pxa_cpu_pm_fns { | 12 | struct 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); |