Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 649de51b authored by Robert Jarzmik's avatar Robert Jarzmik Committed by Russell King
Browse files

[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 711be5cc for
the save registers array (=> overflow).

Signed-off-by: default avatarRobert Jarzmik <rjarzmik@free.fr>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent c8df9a53
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -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;
+3 −5
Original line number Diff line number Diff line
@@ -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,
+3 −5
Original line number Diff line number Diff line
@@ -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,
+3 −4
Original line number Diff line number Diff line
@@ -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,
+3 −5
Original line number Diff line number Diff line
@@ -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;

Loading