diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-05 15:14:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-05 15:14:50 -0500 |
commit | 9b3499d752fc292f37503e5c3a5e5df4f7e76d42 (patch) | |
tree | 07f2c8c9d191be7b2b0ad836136be1ef753697fa | |
parent | b21172cf6dc6e2af21346e774ea2e7c784de30bd (diff) | |
parent | eda9cec4c9a12208a6f69fbe68f72a6311d50032 (diff) |
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"
-rw-r--r-- | arch/ia64/include/asm/acpi.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/acpi.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/module.c | 13 | ||||
-rw-r--r-- | arch/x86/mm/tlb.c | 17 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 2 | ||||
-rw-r--r-- | drivers/idle/intel_idle.c | 9 |
6 files changed, 38 insertions, 7 deletions
diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index c86a947f5368..a3d0211970e9 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h | |||
@@ -112,6 +112,8 @@ static inline void arch_acpi_set_pdc_bits(u32 *buf) | |||
112 | buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; | 112 | buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; |
113 | } | 113 | } |
114 | 114 | ||
115 | #define acpi_unlazy_tlb(x) | ||
116 | |||
115 | #ifdef CONFIG_ACPI_NUMA | 117 | #ifdef CONFIG_ACPI_NUMA |
116 | extern cpumask_t early_cpu_possible_map; | 118 | extern cpumask_t early_cpu_possible_map; |
117 | #define for_each_possible_early_cpu(cpu) \ | 119 | #define for_each_possible_early_cpu(cpu) \ |
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 72d867f6b518..8d0ec9df1cbe 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h | |||
@@ -150,6 +150,8 @@ static inline void disable_acpi(void) { } | |||
150 | extern int x86_acpi_numa_init(void); | 150 | extern int x86_acpi_numa_init(void); |
151 | #endif /* CONFIG_ACPI_NUMA */ | 151 | #endif /* CONFIG_ACPI_NUMA */ |
152 | 152 | ||
153 | #define acpi_unlazy_tlb(x) leave_mm(x) | ||
154 | |||
153 | #ifdef CONFIG_ACPI_APEI | 155 | #ifdef CONFIG_ACPI_APEI |
154 | static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr) | 156 | static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr) |
155 | { | 157 | { |
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index 62e7d70aadd5..da0c160e5589 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c | |||
@@ -172,19 +172,27 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
172 | case R_X86_64_NONE: | 172 | case R_X86_64_NONE: |
173 | break; | 173 | break; |
174 | case R_X86_64_64: | 174 | case R_X86_64_64: |
175 | if (*(u64 *)loc != 0) | ||
176 | goto invalid_relocation; | ||
175 | *(u64 *)loc = val; | 177 | *(u64 *)loc = val; |
176 | break; | 178 | break; |
177 | case R_X86_64_32: | 179 | case R_X86_64_32: |
180 | if (*(u32 *)loc != 0) | ||
181 | goto invalid_relocation; | ||
178 | *(u32 *)loc = val; | 182 | *(u32 *)loc = val; |
179 | if (val != *(u32 *)loc) | 183 | if (val != *(u32 *)loc) |
180 | goto overflow; | 184 | goto overflow; |
181 | break; | 185 | break; |
182 | case R_X86_64_32S: | 186 | case R_X86_64_32S: |
187 | if (*(s32 *)loc != 0) | ||
188 | goto invalid_relocation; | ||
183 | *(s32 *)loc = val; | 189 | *(s32 *)loc = val; |
184 | if ((s64)val != *(s32 *)loc) | 190 | if ((s64)val != *(s32 *)loc) |
185 | goto overflow; | 191 | goto overflow; |
186 | break; | 192 | break; |
187 | case R_X86_64_PC32: | 193 | case R_X86_64_PC32: |
194 | if (*(u32 *)loc != 0) | ||
195 | goto invalid_relocation; | ||
188 | val -= (u64)loc; | 196 | val -= (u64)loc; |
189 | *(u32 *)loc = val; | 197 | *(u32 *)loc = val; |
190 | #if 0 | 198 | #if 0 |
@@ -200,6 +208,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
200 | } | 208 | } |
201 | return 0; | 209 | return 0; |
202 | 210 | ||
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 | |||
203 | overflow: | 216 | overflow: |
204 | pr_err("overflow in relocation type %d val %Lx\n", | 217 | pr_err("overflow in relocation type %d val %Lx\n", |
205 | (int)ELF64_R_TYPE(rel[i].r_info), val); | 218 | (int)ELF64_R_TYPE(rel[i].r_info), val); |
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 0f3d0cea4d00..3118392cdf75 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c | |||
@@ -85,6 +85,7 @@ void leave_mm(int cpu) | |||
85 | 85 | ||
86 | switch_mm(NULL, &init_mm, NULL); | 86 | switch_mm(NULL, &init_mm, NULL); |
87 | } | 87 | } |
88 | EXPORT_SYMBOL_GPL(leave_mm); | ||
88 | 89 | ||
89 | void switch_mm(struct mm_struct *prev, struct mm_struct *next, | 90 | void switch_mm(struct mm_struct *prev, struct mm_struct *next, |
90 | struct task_struct *tsk) | 91 | struct task_struct *tsk) |
@@ -195,12 +196,22 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, | |||
195 | this_cpu_write(cpu_tlbstate.ctxs[new_asid].ctx_id, next->context.ctx_id); | 196 | this_cpu_write(cpu_tlbstate.ctxs[new_asid].ctx_id, next->context.ctx_id); |
196 | this_cpu_write(cpu_tlbstate.ctxs[new_asid].tlb_gen, next_tlb_gen); | 197 | this_cpu_write(cpu_tlbstate.ctxs[new_asid].tlb_gen, next_tlb_gen); |
197 | write_cr3(build_cr3(next, new_asid)); | 198 | write_cr3(build_cr3(next, new_asid)); |
198 | trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, | 199 | |
199 | TLB_FLUSH_ALL); | 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); | ||
200 | } else { | 209 | } else { |
201 | /* The new ASID is already up to date. */ | 210 | /* The new ASID is already up to date. */ |
202 | write_cr3(build_cr3_noflush(next, new_asid)); | 211 | 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); | ||
204 | } | 215 | } |
205 | 216 | ||
206 | this_cpu_write(cpu_tlbstate.loaded_mm, next); | 217 | this_cpu_write(cpu_tlbstate.loaded_mm, next); |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2736e25e9dc6..d50a7b6ccddd 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -710,6 +710,8 @@ static DEFINE_RAW_SPINLOCK(c3_lock); | |||
710 | static void acpi_idle_enter_bm(struct acpi_processor *pr, | 710 | static void acpi_idle_enter_bm(struct acpi_processor *pr, |
711 | struct acpi_processor_cx *cx, bool timer_bc) | 711 | struct acpi_processor_cx *cx, bool timer_bc) |
712 | { | 712 | { |
713 | acpi_unlazy_tlb(smp_processor_id()); | ||
714 | |||
713 | /* | 715 | /* |
714 | * Must be done before busmaster disable as we might need to | 716 | * Must be done before busmaster disable as we might need to |
715 | * access HPET ! | 717 | * access HPET ! |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 5dc7ea4b6bc4..f0b06b14e782 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -913,15 +913,16 @@ static __cpuidle int intel_idle(struct cpuidle_device *dev, | |||
913 | struct cpuidle_state *state = &drv->states[index]; | 913 | struct cpuidle_state *state = &drv->states[index]; |
914 | unsigned long eax = flg2MWAIT(state->flags); | 914 | unsigned long eax = flg2MWAIT(state->flags); |
915 | unsigned int cstate; | 915 | unsigned int cstate; |
916 | int cpu = smp_processor_id(); | ||
916 | 917 | ||
917 | cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1; | 918 | cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1; |
918 | 919 | ||
919 | /* | 920 | /* |
920 | * NB: if CPUIDLE_FLAG_TLB_FLUSHED is set, this idle transition | 921 | * leave_mm() to avoid costly and often unnecessary wakeups |
921 | * will probably flush the TLB. It's not guaranteed to flush | 922 | * for flushing the user TLB's associated with the active mm. |
922 | * the TLB, though, so it's not clear that we can do anything | ||
923 | * useful with this knowledge. | ||
924 | */ | 923 | */ |
924 | if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED) | ||
925 | leave_mm(cpu); | ||
925 | 926 | ||
926 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) | 927 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) |
927 | tick_broadcast_enter(); | 928 | tick_broadcast_enter(); |