Skip to content

Commit 0aeeb3e

Browse files
committed
Merge branches 'pm-sleep' and 'pm-cpufreq'
* pm-sleep: PM / hibernate: Restore processor state before using per-CPU variables x86/power/64: Always create temporary identity mapping correctly * pm-cpufreq: cpufreq: powernv: Fix crash in gpstate_timer_handler()
3 parents 29b4817 + 62822e2 + 8e85946 commit 0aeeb3e

File tree

5 files changed

+36
-14
lines changed

5 files changed

+36
-14
lines changed

arch/x86/include/asm/init.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ struct x86_mapping_info {
55
void *(*alloc_pgt_page)(void *); /* allocate buf for page table */
66
void *context; /* context for alloc_pgt_page */
77
unsigned long pmd_flag; /* page flag for PMD entry */
8-
bool kernel_mapping; /* kernel mapping or ident mapping */
8+
unsigned long offset; /* ident mapping offset */
99
};
1010

1111
int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
12-
unsigned long addr, unsigned long end);
12+
unsigned long pstart, unsigned long pend);
1313

1414
#endif /* _ASM_X86_INIT_H */

arch/x86/mm/ident_map.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
* included by both the compressed kernel and the regular kernel.
44
*/
55

6-
static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page,
6+
static void ident_pmd_init(struct x86_mapping_info *info, pmd_t *pmd_page,
77
unsigned long addr, unsigned long end)
88
{
99
addr &= PMD_MASK;
1010
for (; addr < end; addr += PMD_SIZE) {
1111
pmd_t *pmd = pmd_page + pmd_index(addr);
1212

13-
if (!pmd_present(*pmd))
14-
set_pmd(pmd, __pmd(addr | pmd_flag));
13+
if (pmd_present(*pmd))
14+
continue;
15+
16+
set_pmd(pmd, __pmd((addr - info->offset) | info->pmd_flag));
1517
}
1618
}
1719

@@ -30,28 +32,29 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
3032

3133
if (pud_present(*pud)) {
3234
pmd = pmd_offset(pud, 0);
33-
ident_pmd_init(info->pmd_flag, pmd, addr, next);
35+
ident_pmd_init(info, pmd, addr, next);
3436
continue;
3537
}
3638
pmd = (pmd_t *)info->alloc_pgt_page(info->context);
3739
if (!pmd)
3840
return -ENOMEM;
39-
ident_pmd_init(info->pmd_flag, pmd, addr, next);
41+
ident_pmd_init(info, pmd, addr, next);
4042
set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
4143
}
4244

4345
return 0;
4446
}
4547

4648
int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
47-
unsigned long addr, unsigned long end)
49+
unsigned long pstart, unsigned long pend)
4850
{
51+
unsigned long addr = pstart + info->offset;
52+
unsigned long end = pend + info->offset;
4953
unsigned long next;
5054
int result;
51-
int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
5255

5356
for (; addr < end; addr = next) {
54-
pgd_t *pgd = pgd_page + pgd_index(addr) + off;
57+
pgd_t *pgd = pgd_page + pgd_index(addr);
5558
pud_t *pud;
5659

5760
next = (addr & PGDIR_MASK) + PGDIR_SIZE;

arch/x86/power/hibernate_64.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ static int set_up_temporary_mappings(void)
8787
struct x86_mapping_info info = {
8888
.alloc_pgt_page = alloc_pgt_page,
8989
.pmd_flag = __PAGE_KERNEL_LARGE_EXEC,
90-
.kernel_mapping = true,
90+
.offset = __PAGE_OFFSET,
9191
};
9292
unsigned long mstart, mend;
9393
pgd_t *pgd;

drivers/cpufreq/powernv-cpufreq.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,30 @@ static struct powernv_pstate_info {
145145
/* Use following macros for conversions between pstate_id and index */
146146
static inline int idx_to_pstate(unsigned int i)
147147
{
148+
if (unlikely(i >= powernv_pstate_info.nr_pstates)) {
149+
pr_warn_once("index %u is out of bound\n", i);
150+
return powernv_freqs[powernv_pstate_info.nominal].driver_data;
151+
}
152+
148153
return powernv_freqs[i].driver_data;
149154
}
150155

151156
static inline unsigned int pstate_to_idx(int pstate)
152157
{
158+
int min = powernv_freqs[powernv_pstate_info.min].driver_data;
159+
int max = powernv_freqs[powernv_pstate_info.max].driver_data;
160+
161+
if (min > 0) {
162+
if (unlikely((pstate < max) || (pstate > min))) {
163+
pr_warn_once("pstate %d is out of bound\n", pstate);
164+
return powernv_pstate_info.nominal;
165+
}
166+
} else {
167+
if (unlikely((pstate > max) || (pstate < min))) {
168+
pr_warn_once("pstate %d is out of bound\n", pstate);
169+
return powernv_pstate_info.nominal;
170+
}
171+
}
153172
/*
154173
* abs() is deliberately used so that is works with
155174
* both monotonically increasing and decreasing
@@ -593,7 +612,7 @@ void gpstate_timer_handler(unsigned long data)
593612
} else {
594613
gpstate_idx = calc_global_pstate(gpstates->elapsed_time,
595614
gpstates->highest_lpstate_idx,
596-
freq_data.pstate_id);
615+
gpstates->last_lpstate_idx);
597616
}
598617

599618
/*

kernel/power/hibernate.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,12 +300,12 @@ static int create_image(int platform_mode)
300300
save_processor_state();
301301
trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, true);
302302
error = swsusp_arch_suspend();
303+
/* Restore control flow magically appears here */
304+
restore_processor_state();
303305
trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, false);
304306
if (error)
305307
printk(KERN_ERR "PM: Error %d creating hibernation image\n",
306308
error);
307-
/* Restore control flow magically appears here */
308-
restore_processor_state();
309309
if (!in_suspend)
310310
events_check_enabled = false;
311311

0 commit comments

Comments
 (0)