Skip to content

Commit 9b3499d

Browse files
committed
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar: "Two fixes: - A PCID related revert that fixes power management and performance regressions. - The module loader robustization and sanity check commit is rather fresh, but it looked like a good idea to apply because of the hidden data corruption problem such invalid modules could cause" * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/module: Detect and skip invalid relocations Revert "x86/mm: Stop calling leave_mm() in idle code"
2 parents b21172c + eda9cec commit 9b3499d

File tree

6 files changed

+38
-7
lines changed

6 files changed

+38
-7
lines changed

arch/ia64/include/asm/acpi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ static inline void arch_acpi_set_pdc_bits(u32 *buf)
112112
buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
113113
}
114114

115+
#define acpi_unlazy_tlb(x)
116+
115117
#ifdef CONFIG_ACPI_NUMA
116118
extern cpumask_t early_cpu_possible_map;
117119
#define for_each_possible_early_cpu(cpu) \

arch/x86/include/asm/acpi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ static inline void disable_acpi(void) { }
150150
extern int x86_acpi_numa_init(void);
151151
#endif /* CONFIG_ACPI_NUMA */
152152

153+
#define acpi_unlazy_tlb(x) leave_mm(x)
154+
153155
#ifdef CONFIG_ACPI_APEI
154156
static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
155157
{

arch/x86/kernel/module.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,19 +172,27 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
172172
case R_X86_64_NONE:
173173
break;
174174
case R_X86_64_64:
175+
if (*(u64 *)loc != 0)
176+
goto invalid_relocation;
175177
*(u64 *)loc = val;
176178
break;
177179
case R_X86_64_32:
180+
if (*(u32 *)loc != 0)
181+
goto invalid_relocation;
178182
*(u32 *)loc = val;
179183
if (val != *(u32 *)loc)
180184
goto overflow;
181185
break;
182186
case R_X86_64_32S:
187+
if (*(s32 *)loc != 0)
188+
goto invalid_relocation;
183189
*(s32 *)loc = val;
184190
if ((s64)val != *(s32 *)loc)
185191
goto overflow;
186192
break;
187193
case R_X86_64_PC32:
194+
if (*(u32 *)loc != 0)
195+
goto invalid_relocation;
188196
val -= (u64)loc;
189197
*(u32 *)loc = val;
190198
#if 0
@@ -200,6 +208,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
200208
}
201209
return 0;
202210

211+
invalid_relocation:
212+
pr_err("x86/modules: Skipping invalid relocation target, existing value is nonzero for type %d, loc %p, val %Lx\n",
213+
(int)ELF64_R_TYPE(rel[i].r_info), loc, val);
214+
return -ENOEXEC;
215+
203216
overflow:
204217
pr_err("overflow in relocation type %d val %Lx\n",
205218
(int)ELF64_R_TYPE(rel[i].r_info), val);

arch/x86/mm/tlb.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ void leave_mm(int cpu)
8585

8686
switch_mm(NULL, &init_mm, NULL);
8787
}
88+
EXPORT_SYMBOL_GPL(leave_mm);
8889

8990
void switch_mm(struct mm_struct *prev, struct mm_struct *next,
9091
struct task_struct *tsk)
@@ -195,12 +196,22 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
195196
this_cpu_write(cpu_tlbstate.ctxs[new_asid].ctx_id, next->context.ctx_id);
196197
this_cpu_write(cpu_tlbstate.ctxs[new_asid].tlb_gen, next_tlb_gen);
197198
write_cr3(build_cr3(next, new_asid));
198-
trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH,
199-
TLB_FLUSH_ALL);
199+
200+
/*
201+
* NB: This gets called via leave_mm() in the idle path
202+
* where RCU functions differently. Tracing normally
203+
* uses RCU, so we need to use the _rcuidle variant.
204+
*
205+
* (There is no good reason for this. The idle code should
206+
* be rearranged to call this before rcu_idle_enter().)
207+
*/
208+
trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
200209
} else {
201210
/* The new ASID is already up to date. */
202211
write_cr3(build_cr3_noflush(next, new_asid));
203-
trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, 0);
212+
213+
/* See above wrt _rcuidle. */
214+
trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, 0);
204215
}
205216

206217
this_cpu_write(cpu_tlbstate.loaded_mm, next);

drivers/acpi/processor_idle.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,8 @@ static DEFINE_RAW_SPINLOCK(c3_lock);
710710
static void acpi_idle_enter_bm(struct acpi_processor *pr,
711711
struct acpi_processor_cx *cx, bool timer_bc)
712712
{
713+
acpi_unlazy_tlb(smp_processor_id());
714+
713715
/*
714716
* Must be done before busmaster disable as we might need to
715717
* access HPET !

drivers/idle/intel_idle.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -913,15 +913,16 @@ static __cpuidle int intel_idle(struct cpuidle_device *dev,
913913
struct cpuidle_state *state = &drv->states[index];
914914
unsigned long eax = flg2MWAIT(state->flags);
915915
unsigned int cstate;
916+
int cpu = smp_processor_id();
916917

917918
cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1;
918919

919920
/*
920-
* NB: if CPUIDLE_FLAG_TLB_FLUSHED is set, this idle transition
921-
* will probably flush the TLB. It's not guaranteed to flush
922-
* the TLB, though, so it's not clear that we can do anything
923-
* useful with this knowledge.
921+
* leave_mm() to avoid costly and often unnecessary wakeups
922+
* for flushing the user TLB's associated with the active mm.
924923
*/
924+
if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED)
925+
leave_mm(cpu);
925926

926927
if (!(lapic_timer_reliable_states & (1 << (cstate))))
927928
tick_broadcast_enter();

0 commit comments

Comments
 (0)