diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/amd_nb.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/amd.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel.c | 10 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/amd_early.c | 43 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mtrr/generic.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/ftrace.c | 83 | ||||
-rw-r--r-- | arch/x86/kernel/irq.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/quirks.c | 37 | ||||
-rw-r--r-- | arch/x86/kernel/tsc.c | 4 |
10 files changed, 136 insertions, 68 deletions
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 59554dca96ec..dec8de4e1663 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c | |||
@@ -179,7 +179,7 @@ int amd_get_subcaches(int cpu) | |||
179 | return (mask >> (4 * cuid)) & 0xf; | 179 | return (mask >> (4 * cuid)) & 0xf; |
180 | } | 180 | } |
181 | 181 | ||
182 | int amd_set_subcaches(int cpu, int mask) | 182 | int amd_set_subcaches(int cpu, unsigned long mask) |
183 | { | 183 | { |
184 | static unsigned int reset, ban; | 184 | static unsigned int reset, ban; |
185 | struct amd_northbridge *nb = node_to_amd_nb(amd_get_nb_id(cpu)); | 185 | struct amd_northbridge *nb = node_to_amd_nb(amd_get_nb_id(cpu)); |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index d3153e281d72..c67ffa686064 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -767,10 +767,7 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) | |||
767 | 767 | ||
768 | static void cpu_set_tlb_flushall_shift(struct cpuinfo_x86 *c) | 768 | static void cpu_set_tlb_flushall_shift(struct cpuinfo_x86 *c) |
769 | { | 769 | { |
770 | tlb_flushall_shift = 5; | 770 | tlb_flushall_shift = 6; |
771 | |||
772 | if (c->x86 <= 0x11) | ||
773 | tlb_flushall_shift = 4; | ||
774 | } | 771 | } |
775 | 772 | ||
776 | static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) | 773 | static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 24b6fd10625a..8e28bf2fc3ef 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -284,8 +284,13 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c) | |||
284 | raw_local_save_flags(eflags); | 284 | raw_local_save_flags(eflags); |
285 | BUG_ON(eflags & X86_EFLAGS_AC); | 285 | BUG_ON(eflags & X86_EFLAGS_AC); |
286 | 286 | ||
287 | if (cpu_has(c, X86_FEATURE_SMAP)) | 287 | if (cpu_has(c, X86_FEATURE_SMAP)) { |
288 | #ifdef CONFIG_X86_SMAP | ||
288 | set_in_cr4(X86_CR4_SMAP); | 289 | set_in_cr4(X86_CR4_SMAP); |
290 | #else | ||
291 | clear_in_cr4(X86_CR4_SMAP); | ||
292 | #endif | ||
293 | } | ||
289 | } | 294 | } |
290 | 295 | ||
291 | /* | 296 | /* |
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 3db61c644e44..5cd9bfabd645 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -640,21 +640,17 @@ static void intel_tlb_flushall_shift_set(struct cpuinfo_x86 *c) | |||
640 | case 0x61d: /* six-core 45 nm xeon "Dunnington" */ | 640 | case 0x61d: /* six-core 45 nm xeon "Dunnington" */ |
641 | tlb_flushall_shift = -1; | 641 | tlb_flushall_shift = -1; |
642 | break; | 642 | break; |
643 | case 0x63a: /* Ivybridge */ | ||
644 | tlb_flushall_shift = 2; | ||
645 | break; | ||
643 | case 0x61a: /* 45 nm nehalem, "Bloomfield" */ | 646 | case 0x61a: /* 45 nm nehalem, "Bloomfield" */ |
644 | case 0x61e: /* 45 nm nehalem, "Lynnfield" */ | 647 | case 0x61e: /* 45 nm nehalem, "Lynnfield" */ |
645 | case 0x625: /* 32 nm nehalem, "Clarkdale" */ | 648 | case 0x625: /* 32 nm nehalem, "Clarkdale" */ |
646 | case 0x62c: /* 32 nm nehalem, "Gulftown" */ | 649 | case 0x62c: /* 32 nm nehalem, "Gulftown" */ |
647 | case 0x62e: /* 45 nm nehalem-ex, "Beckton" */ | 650 | case 0x62e: /* 45 nm nehalem-ex, "Beckton" */ |
648 | case 0x62f: /* 32 nm Xeon E7 */ | 651 | case 0x62f: /* 32 nm Xeon E7 */ |
649 | tlb_flushall_shift = 6; | ||
650 | break; | ||
651 | case 0x62a: /* SandyBridge */ | 652 | case 0x62a: /* SandyBridge */ |
652 | case 0x62d: /* SandyBridge, "Romely-EP" */ | 653 | case 0x62d: /* SandyBridge, "Romely-EP" */ |
653 | tlb_flushall_shift = 5; | ||
654 | break; | ||
655 | case 0x63a: /* Ivybridge */ | ||
656 | tlb_flushall_shift = 1; | ||
657 | break; | ||
658 | default: | 654 | default: |
659 | tlb_flushall_shift = 6; | 655 | tlb_flushall_shift = 6; |
660 | } | 656 | } |
diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c index 8384c0fa206f..617a9e284245 100644 --- a/arch/x86/kernel/cpu/microcode/amd_early.c +++ b/arch/x86/kernel/cpu/microcode/amd_early.c | |||
@@ -285,6 +285,15 @@ static void __init collect_cpu_sig_on_bsp(void *arg) | |||
285 | 285 | ||
286 | uci->cpu_sig.sig = cpuid_eax(0x00000001); | 286 | uci->cpu_sig.sig = cpuid_eax(0x00000001); |
287 | } | 287 | } |
288 | |||
289 | static void __init get_bsp_sig(void) | ||
290 | { | ||
291 | unsigned int bsp = boot_cpu_data.cpu_index; | ||
292 | struct ucode_cpu_info *uci = ucode_cpu_info + bsp; | ||
293 | |||
294 | if (!uci->cpu_sig.sig) | ||
295 | smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1); | ||
296 | } | ||
288 | #else | 297 | #else |
289 | void load_ucode_amd_ap(void) | 298 | void load_ucode_amd_ap(void) |
290 | { | 299 | { |
@@ -337,31 +346,37 @@ void load_ucode_amd_ap(void) | |||
337 | 346 | ||
338 | int __init save_microcode_in_initrd_amd(void) | 347 | int __init save_microcode_in_initrd_amd(void) |
339 | { | 348 | { |
349 | unsigned long cont; | ||
340 | enum ucode_state ret; | 350 | enum ucode_state ret; |
341 | u32 eax; | 351 | u32 eax; |
342 | 352 | ||
343 | #ifdef CONFIG_X86_32 | 353 | if (!container) |
344 | unsigned int bsp = boot_cpu_data.cpu_index; | 354 | return -EINVAL; |
345 | struct ucode_cpu_info *uci = ucode_cpu_info + bsp; | ||
346 | |||
347 | if (!uci->cpu_sig.sig) | ||
348 | smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1); | ||
349 | 355 | ||
356 | #ifdef CONFIG_X86_32 | ||
357 | get_bsp_sig(); | ||
358 | cont = (unsigned long)container; | ||
359 | #else | ||
350 | /* | 360 | /* |
351 | * Take into account the fact that the ramdisk might get relocated | 361 | * We need the physical address of the container for both bitness since |
352 | * and therefore we need to recompute the container's position in | 362 | * boot_params.hdr.ramdisk_image is a physical address. |
353 | * virtual memory space. | ||
354 | */ | 363 | */ |
355 | container = (u8 *)(__va((u32)relocated_ramdisk) + | 364 | cont = __pa(container); |
356 | ((u32)container - boot_params.hdr.ramdisk_image)); | ||
357 | #endif | 365 | #endif |
366 | |||
367 | /* | ||
368 | * Take into account the fact that the ramdisk might get relocated and | ||
369 | * therefore we need to recompute the container's position in virtual | ||
370 | * memory space. | ||
371 | */ | ||
372 | if (relocated_ramdisk) | ||
373 | container = (u8 *)(__va(relocated_ramdisk) + | ||
374 | (cont - boot_params.hdr.ramdisk_image)); | ||
375 | |||
358 | if (ucode_new_rev) | 376 | if (ucode_new_rev) |
359 | pr_info("microcode: updated early to new patch_level=0x%08x\n", | 377 | pr_info("microcode: updated early to new patch_level=0x%08x\n", |
360 | ucode_new_rev); | 378 | ucode_new_rev); |
361 | 379 | ||
362 | if (!container) | ||
363 | return -EINVAL; | ||
364 | |||
365 | eax = cpuid_eax(0x00000001); | 380 | eax = cpuid_eax(0x00000001); |
366 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); | 381 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); |
367 | 382 | ||
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index ce2d0a2c3e4f..0e25a1bc5ab5 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c | |||
@@ -683,7 +683,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock) | |||
683 | } | 683 | } |
684 | 684 | ||
685 | /* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */ | 685 | /* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */ |
686 | count_vm_event(NR_TLB_LOCAL_FLUSH_ALL); | 686 | count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL); |
687 | __flush_tlb(); | 687 | __flush_tlb(); |
688 | 688 | ||
689 | /* Save MTRR state */ | 689 | /* Save MTRR state */ |
@@ -697,7 +697,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock) | |||
697 | static void post_set(void) __releases(set_atomicity_lock) | 697 | static void post_set(void) __releases(set_atomicity_lock) |
698 | { | 698 | { |
699 | /* Flush TLBs (no need to flush caches - they are disabled) */ | 699 | /* Flush TLBs (no need to flush caches - they are disabled) */ |
700 | count_vm_event(NR_TLB_LOCAL_FLUSH_ALL); | 700 | count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL); |
701 | __flush_tlb(); | 701 | __flush_tlb(); |
702 | 702 | ||
703 | /* Intel (P6) standard MTRRs */ | 703 | /* Intel (P6) standard MTRRs */ |
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index d4bdd253fea7..e6253195a301 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c | |||
@@ -77,8 +77,7 @@ within(unsigned long addr, unsigned long start, unsigned long end) | |||
77 | return addr >= start && addr < end; | 77 | return addr >= start && addr < end; |
78 | } | 78 | } |
79 | 79 | ||
80 | static int | 80 | static unsigned long text_ip_addr(unsigned long ip) |
81 | do_ftrace_mod_code(unsigned long ip, const void *new_code) | ||
82 | { | 81 | { |
83 | /* | 82 | /* |
84 | * On x86_64, kernel text mappings are mapped read-only with | 83 | * On x86_64, kernel text mappings are mapped read-only with |
@@ -91,7 +90,7 @@ do_ftrace_mod_code(unsigned long ip, const void *new_code) | |||
91 | if (within(ip, (unsigned long)_text, (unsigned long)_etext)) | 90 | if (within(ip, (unsigned long)_text, (unsigned long)_etext)) |
92 | ip = (unsigned long)__va(__pa_symbol(ip)); | 91 | ip = (unsigned long)__va(__pa_symbol(ip)); |
93 | 92 | ||
94 | return probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE); | 93 | return ip; |
95 | } | 94 | } |
96 | 95 | ||
97 | static const unsigned char *ftrace_nop_replace(void) | 96 | static const unsigned char *ftrace_nop_replace(void) |
@@ -123,8 +122,10 @@ ftrace_modify_code_direct(unsigned long ip, unsigned const char *old_code, | |||
123 | if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0) | 122 | if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0) |
124 | return -EINVAL; | 123 | return -EINVAL; |
125 | 124 | ||
125 | ip = text_ip_addr(ip); | ||
126 | |||
126 | /* replace the text with the new text */ | 127 | /* replace the text with the new text */ |
127 | if (do_ftrace_mod_code(ip, new_code)) | 128 | if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE)) |
128 | return -EPERM; | 129 | return -EPERM; |
129 | 130 | ||
130 | sync_core(); | 131 | sync_core(); |
@@ -221,37 +222,51 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, | |||
221 | return -EINVAL; | 222 | return -EINVAL; |
222 | } | 223 | } |
223 | 224 | ||
224 | int ftrace_update_ftrace_func(ftrace_func_t func) | 225 | static unsigned long ftrace_update_func; |
226 | |||
227 | static int update_ftrace_func(unsigned long ip, void *new) | ||
225 | { | 228 | { |
226 | unsigned long ip = (unsigned long)(&ftrace_call); | 229 | unsigned char old[MCOUNT_INSN_SIZE]; |
227 | unsigned char old[MCOUNT_INSN_SIZE], *new; | ||
228 | int ret; | 230 | int ret; |
229 | 231 | ||
230 | memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); | 232 | memcpy(old, (void *)ip, MCOUNT_INSN_SIZE); |
231 | new = ftrace_call_replace(ip, (unsigned long)func); | 233 | |
234 | ftrace_update_func = ip; | ||
235 | /* Make sure the breakpoints see the ftrace_update_func update */ | ||
236 | smp_wmb(); | ||
232 | 237 | ||
233 | /* See comment above by declaration of modifying_ftrace_code */ | 238 | /* See comment above by declaration of modifying_ftrace_code */ |
234 | atomic_inc(&modifying_ftrace_code); | 239 | atomic_inc(&modifying_ftrace_code); |
235 | 240 | ||
236 | ret = ftrace_modify_code(ip, old, new); | 241 | ret = ftrace_modify_code(ip, old, new); |
237 | 242 | ||
243 | atomic_dec(&modifying_ftrace_code); | ||
244 | |||
245 | return ret; | ||
246 | } | ||
247 | |||
248 | int ftrace_update_ftrace_func(ftrace_func_t func) | ||
249 | { | ||
250 | unsigned long ip = (unsigned long)(&ftrace_call); | ||
251 | unsigned char *new; | ||
252 | int ret; | ||
253 | |||
254 | new = ftrace_call_replace(ip, (unsigned long)func); | ||
255 | ret = update_ftrace_func(ip, new); | ||
256 | |||
238 | /* Also update the regs callback function */ | 257 | /* Also update the regs callback function */ |
239 | if (!ret) { | 258 | if (!ret) { |
240 | ip = (unsigned long)(&ftrace_regs_call); | 259 | ip = (unsigned long)(&ftrace_regs_call); |
241 | memcpy(old, &ftrace_regs_call, MCOUNT_INSN_SIZE); | ||
242 | new = ftrace_call_replace(ip, (unsigned long)func); | 260 | new = ftrace_call_replace(ip, (unsigned long)func); |
243 | ret = ftrace_modify_code(ip, old, new); | 261 | ret = update_ftrace_func(ip, new); |
244 | } | 262 | } |
245 | 263 | ||
246 | atomic_dec(&modifying_ftrace_code); | ||
247 | |||
248 | return ret; | 264 | return ret; |
249 | } | 265 | } |
250 | 266 | ||
251 | static int is_ftrace_caller(unsigned long ip) | 267 | static int is_ftrace_caller(unsigned long ip) |
252 | { | 268 | { |
253 | if (ip == (unsigned long)(&ftrace_call) || | 269 | if (ip == ftrace_update_func) |
254 | ip == (unsigned long)(&ftrace_regs_call)) | ||
255 | return 1; | 270 | return 1; |
256 | 271 | ||
257 | return 0; | 272 | return 0; |
@@ -677,45 +692,41 @@ int __init ftrace_dyn_arch_init(void *data) | |||
677 | #ifdef CONFIG_DYNAMIC_FTRACE | 692 | #ifdef CONFIG_DYNAMIC_FTRACE |
678 | extern void ftrace_graph_call(void); | 693 | extern void ftrace_graph_call(void); |
679 | 694 | ||
680 | static int ftrace_mod_jmp(unsigned long ip, | 695 | static unsigned char *ftrace_jmp_replace(unsigned long ip, unsigned long addr) |
681 | int old_offset, int new_offset) | ||
682 | { | 696 | { |
683 | unsigned char code[MCOUNT_INSN_SIZE]; | 697 | static union ftrace_code_union calc; |
684 | 698 | ||
685 | if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE)) | 699 | /* Jmp not a call (ignore the .e8) */ |
686 | return -EFAULT; | 700 | calc.e8 = 0xe9; |
701 | calc.offset = ftrace_calc_offset(ip + MCOUNT_INSN_SIZE, addr); | ||
687 | 702 | ||
688 | if (code[0] != 0xe9 || old_offset != *(int *)(&code[1])) | 703 | /* |
689 | return -EINVAL; | 704 | * ftrace external locks synchronize the access to the static variable. |
705 | */ | ||
706 | return calc.code; | ||
707 | } | ||
690 | 708 | ||
691 | *(int *)(&code[1]) = new_offset; | 709 | static int ftrace_mod_jmp(unsigned long ip, void *func) |
710 | { | ||
711 | unsigned char *new; | ||
692 | 712 | ||
693 | if (do_ftrace_mod_code(ip, &code)) | 713 | new = ftrace_jmp_replace(ip, (unsigned long)func); |
694 | return -EPERM; | ||
695 | 714 | ||
696 | return 0; | 715 | return update_ftrace_func(ip, new); |
697 | } | 716 | } |
698 | 717 | ||
699 | int ftrace_enable_ftrace_graph_caller(void) | 718 | int ftrace_enable_ftrace_graph_caller(void) |
700 | { | 719 | { |
701 | unsigned long ip = (unsigned long)(&ftrace_graph_call); | 720 | unsigned long ip = (unsigned long)(&ftrace_graph_call); |
702 | int old_offset, new_offset; | ||
703 | 721 | ||
704 | old_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE); | 722 | return ftrace_mod_jmp(ip, &ftrace_graph_caller); |
705 | new_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE); | ||
706 | |||
707 | return ftrace_mod_jmp(ip, old_offset, new_offset); | ||
708 | } | 723 | } |
709 | 724 | ||
710 | int ftrace_disable_ftrace_graph_caller(void) | 725 | int ftrace_disable_ftrace_graph_caller(void) |
711 | { | 726 | { |
712 | unsigned long ip = (unsigned long)(&ftrace_graph_call); | 727 | unsigned long ip = (unsigned long)(&ftrace_graph_call); |
713 | int old_offset, new_offset; | ||
714 | |||
715 | old_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE); | ||
716 | new_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE); | ||
717 | 728 | ||
718 | return ftrace_mod_jmp(ip, old_offset, new_offset); | 729 | return ftrace_mod_jmp(ip, &ftrace_stub); |
719 | } | 730 | } |
720 | 731 | ||
721 | #endif /* !CONFIG_DYNAMIC_FTRACE */ | 732 | #endif /* !CONFIG_DYNAMIC_FTRACE */ |
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index dbb60878b744..d99f31d9a750 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -266,6 +266,14 @@ __visible void smp_trace_x86_platform_ipi(struct pt_regs *regs) | |||
266 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); | 266 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); |
267 | 267 | ||
268 | #ifdef CONFIG_HOTPLUG_CPU | 268 | #ifdef CONFIG_HOTPLUG_CPU |
269 | |||
270 | /* These two declarations are only used in check_irq_vectors_for_cpu_disable() | ||
271 | * below, which is protected by stop_machine(). Putting them on the stack | ||
272 | * results in a stack frame overflow. Dynamically allocating could result in a | ||
273 | * failure so declare these two cpumasks as global. | ||
274 | */ | ||
275 | static struct cpumask affinity_new, online_new; | ||
276 | |||
269 | /* | 277 | /* |
270 | * This cpu is going to be removed and its vectors migrated to the remaining | 278 | * This cpu is going to be removed and its vectors migrated to the remaining |
271 | * online cpus. Check to see if there are enough vectors in the remaining cpus. | 279 | * online cpus. Check to see if there are enough vectors in the remaining cpus. |
@@ -277,7 +285,6 @@ int check_irq_vectors_for_cpu_disable(void) | |||
277 | unsigned int this_cpu, vector, this_count, count; | 285 | unsigned int this_cpu, vector, this_count, count; |
278 | struct irq_desc *desc; | 286 | struct irq_desc *desc; |
279 | struct irq_data *data; | 287 | struct irq_data *data; |
280 | struct cpumask affinity_new, online_new; | ||
281 | 288 | ||
282 | this_cpu = smp_processor_id(); | 289 | this_cpu = smp_processor_id(); |
283 | cpumask_copy(&online_new, cpu_online_mask); | 290 | cpumask_copy(&online_new, cpu_online_mask); |
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 04ee1e2e4c02..7c6acd4b8995 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c | |||
@@ -571,3 +571,40 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F5, | |||
571 | quirk_amd_nb_node); | 571 | quirk_amd_nb_node); |
572 | 572 | ||
573 | #endif | 573 | #endif |
574 | |||
575 | #ifdef CONFIG_PCI | ||
576 | /* | ||
577 | * Processor does not ensure DRAM scrub read/write sequence | ||
578 | * is atomic wrt accesses to CC6 save state area. Therefore | ||
579 | * if a concurrent scrub read/write access is to same address | ||
580 | * the entry may appear as if it is not written. This quirk | ||
581 | * applies to Fam16h models 00h-0Fh | ||
582 | * | ||
583 | * See "Revision Guide" for AMD F16h models 00h-0fh, | ||
584 | * document 51810 rev. 3.04, Nov 2013 | ||
585 | */ | ||
586 | static void amd_disable_seq_and_redirect_scrub(struct pci_dev *dev) | ||
587 | { | ||
588 | u32 val; | ||
589 | |||
590 | /* | ||
591 | * Suggested workaround: | ||
592 | * set D18F3x58[4:0] = 00h and set D18F3x5C[0] = 0b | ||
593 | */ | ||
594 | pci_read_config_dword(dev, 0x58, &val); | ||
595 | if (val & 0x1F) { | ||
596 | val &= ~(0x1F); | ||
597 | pci_write_config_dword(dev, 0x58, val); | ||
598 | } | ||
599 | |||
600 | pci_read_config_dword(dev, 0x5C, &val); | ||
601 | if (val & BIT(0)) { | ||
602 | val &= ~BIT(0); | ||
603 | pci_write_config_dword(dev, 0x5c, val); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3, | ||
608 | amd_disable_seq_and_redirect_scrub); | ||
609 | |||
610 | #endif | ||
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 19e5adb49a27..acb3b606613e 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
@@ -209,7 +209,7 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc) | |||
209 | * dance when its actually needed. | 209 | * dance when its actually needed. |
210 | */ | 210 | */ |
211 | 211 | ||
212 | preempt_disable(); | 212 | preempt_disable_notrace(); |
213 | data = this_cpu_read(cyc2ns.head); | 213 | data = this_cpu_read(cyc2ns.head); |
214 | tail = this_cpu_read(cyc2ns.tail); | 214 | tail = this_cpu_read(cyc2ns.tail); |
215 | 215 | ||
@@ -229,7 +229,7 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc) | |||
229 | if (!--data->__count) | 229 | if (!--data->__count) |
230 | this_cpu_write(cyc2ns.tail, data); | 230 | this_cpu_write(cyc2ns.tail, data); |
231 | } | 231 | } |
232 | preempt_enable(); | 232 | preempt_enable_notrace(); |
233 | 233 | ||
234 | return ns; | 234 | return ns; |
235 | } | 235 | } |