diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/ds.h | 9 | ||||
-rw-r--r-- | arch/x86/include/asm/msr.h | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/ptrace.h | 7 | ||||
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/Makefile | 5 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_64.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/ds.c | 11 | ||||
-rw-r--r-- | arch/x86/kernel/microcode_core.c | 19 | ||||
-rw-r--r-- | arch/x86/kernel/microcode_intel.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/pci-gart_64.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/process_32.c | 20 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 20 | ||||
-rw-r--r-- | arch/x86/kernel/ptrace.c | 93 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 2 |
15 files changed, 156 insertions, 58 deletions
diff --git a/arch/x86/include/asm/ds.h b/arch/x86/include/asm/ds.h index ee0ea3a96c11..a8f672ba100c 100644 --- a/arch/x86/include/asm/ds.h +++ b/arch/x86/include/asm/ds.h | |||
@@ -252,12 +252,21 @@ extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *); | |||
252 | */ | 252 | */ |
253 | extern void ds_switch_to(struct task_struct *prev, struct task_struct *next); | 253 | extern void ds_switch_to(struct task_struct *prev, struct task_struct *next); |
254 | 254 | ||
255 | /* | ||
256 | * Task clone/init and cleanup work | ||
257 | */ | ||
258 | extern void ds_copy_thread(struct task_struct *tsk, struct task_struct *father); | ||
259 | extern void ds_exit_thread(struct task_struct *tsk); | ||
260 | |||
255 | #else /* CONFIG_X86_DS */ | 261 | #else /* CONFIG_X86_DS */ |
256 | 262 | ||
257 | struct cpuinfo_x86; | 263 | struct cpuinfo_x86; |
258 | static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {} | 264 | static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {} |
259 | static inline void ds_switch_to(struct task_struct *prev, | 265 | static inline void ds_switch_to(struct task_struct *prev, |
260 | struct task_struct *next) {} | 266 | struct task_struct *next) {} |
267 | static inline void ds_copy_thread(struct task_struct *tsk, | ||
268 | struct task_struct *father) {} | ||
269 | static inline void ds_exit_thread(struct task_struct *tsk) {} | ||
261 | 270 | ||
262 | #endif /* CONFIG_X86_DS */ | 271 | #endif /* CONFIG_X86_DS */ |
263 | #endif /* _ASM_X86_DS_H */ | 272 | #endif /* _ASM_X86_DS_H */ |
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index c2a812ebde89..b8a1799ea871 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h | |||
@@ -85,7 +85,8 @@ static inline void native_write_msr(unsigned int msr, | |||
85 | asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory"); | 85 | asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory"); |
86 | } | 86 | } |
87 | 87 | ||
88 | static inline int native_write_msr_safe(unsigned int msr, | 88 | /* Can be uninlined because referenced by paravirt */ |
89 | notrace static inline int native_write_msr_safe(unsigned int msr, | ||
89 | unsigned low, unsigned high) | 90 | unsigned low, unsigned high) |
90 | { | 91 | { |
91 | int err; | 92 | int err; |
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index fbf744215911..6d34d954c228 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h | |||
@@ -235,6 +235,13 @@ extern int do_get_thread_area(struct task_struct *p, int idx, | |||
235 | extern int do_set_thread_area(struct task_struct *p, int idx, | 235 | extern int do_set_thread_area(struct task_struct *p, int idx, |
236 | struct user_desc __user *info, int can_allocate); | 236 | struct user_desc __user *info, int can_allocate); |
237 | 237 | ||
238 | extern void x86_ptrace_untrace(struct task_struct *); | ||
239 | extern void x86_ptrace_fork(struct task_struct *child, | ||
240 | unsigned long clone_flags); | ||
241 | |||
242 | #define arch_ptrace_untrace(tsk) x86_ptrace_untrace(tsk) | ||
243 | #define arch_ptrace_fork(child, flags) x86_ptrace_fork(child, flags) | ||
244 | |||
238 | #endif /* __KERNEL__ */ | 245 | #endif /* __KERNEL__ */ |
239 | 246 | ||
240 | #endif /* !__ASSEMBLY__ */ | 247 | #endif /* !__ASSEMBLY__ */ |
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index a7b6dec6fc3f..0a60d60ed036 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c | |||
@@ -235,8 +235,9 @@ static int iommu_completion_wait(struct amd_iommu *iommu) | |||
235 | status &= ~MMIO_STATUS_COM_WAIT_INT_MASK; | 235 | status &= ~MMIO_STATUS_COM_WAIT_INT_MASK; |
236 | writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET); | 236 | writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET); |
237 | 237 | ||
238 | if (unlikely((i == EXIT_LOOP_COUNT) && printk_ratelimit())) | 238 | if (unlikely(i == EXIT_LOOP_COUNT)) |
239 | printk(KERN_WARNING "AMD IOMMU: Completion wait loop failed\n"); | 239 | panic("AMD IOMMU: Completion wait loop failed\n"); |
240 | |||
240 | out: | 241 | out: |
241 | spin_unlock_irqrestore(&iommu->lock, flags); | 242 | spin_unlock_irqrestore(&iommu->lock, flags); |
242 | 243 | ||
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 30ae2701b3df..c6cc22815d35 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
@@ -427,6 +427,10 @@ static u8 * __init alloc_command_buffer(struct amd_iommu *iommu) | |||
427 | memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET, | 427 | memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET, |
428 | &entry, sizeof(entry)); | 428 | &entry, sizeof(entry)); |
429 | 429 | ||
430 | /* set head and tail to zero manually */ | ||
431 | writel(0x00, iommu->mmio_base + MMIO_CMD_HEAD_OFFSET); | ||
432 | writel(0x00, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET); | ||
433 | |||
430 | iommu_feature_enable(iommu, CONTROL_CMDBUF_EN); | 434 | iommu_feature_enable(iommu, CONTROL_CMDBUF_EN); |
431 | 435 | ||
432 | return cmd_buf; | 436 | return cmd_buf; |
@@ -1074,7 +1078,8 @@ int __init amd_iommu_init(void) | |||
1074 | goto free; | 1078 | goto free; |
1075 | 1079 | ||
1076 | /* IOMMU rlookup table - find the IOMMU for a specific device */ | 1080 | /* IOMMU rlookup table - find the IOMMU for a specific device */ |
1077 | amd_iommu_rlookup_table = (void *)__get_free_pages(GFP_KERNEL, | 1081 | amd_iommu_rlookup_table = (void *)__get_free_pages( |
1082 | GFP_KERNEL | __GFP_ZERO, | ||
1078 | get_order(rlookup_table_size)); | 1083 | get_order(rlookup_table_size)); |
1079 | if (amd_iommu_rlookup_table == NULL) | 1084 | if (amd_iommu_rlookup_table == NULL) |
1080 | goto free; | 1085 | goto free; |
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 82ec6075c057..4ae495a313f3 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile | |||
@@ -2,6 +2,11 @@ | |||
2 | # Makefile for x86-compatible CPU details and quirks | 2 | # Makefile for x86-compatible CPU details and quirks |
3 | # | 3 | # |
4 | 4 | ||
5 | # Don't trace early stages of a secondary CPU boot | ||
6 | ifdef CONFIG_FUNCTION_TRACER | ||
7 | CFLAGS_REMOVE_common.o = -pg | ||
8 | endif | ||
9 | |||
5 | obj-y := intel_cacheinfo.o addon_cpuid_features.o | 10 | obj-y := intel_cacheinfo.o addon_cpuid_features.o |
6 | obj-y += proc.o capflags.o powerflags.o common.o | 11 | obj-y += proc.o capflags.o powerflags.o common.o |
7 | 12 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index 4b031a4ac856..1c838032fd37 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c | |||
@@ -510,12 +510,9 @@ static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c) | |||
510 | */ | 510 | */ |
511 | void __cpuinit mcheck_init(struct cpuinfo_x86 *c) | 511 | void __cpuinit mcheck_init(struct cpuinfo_x86 *c) |
512 | { | 512 | { |
513 | static cpumask_t mce_cpus = CPU_MASK_NONE; | ||
514 | |||
515 | mce_cpu_quirks(c); | 513 | mce_cpu_quirks(c); |
516 | 514 | ||
517 | if (mce_dont_init || | 515 | if (mce_dont_init || |
518 | cpu_test_and_set(smp_processor_id(), mce_cpus) || | ||
519 | !mce_available(c)) | 516 | !mce_available(c)) |
520 | return; | 517 | return; |
521 | 518 | ||
diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index 98d271e60e08..da91701a2348 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c | |||
@@ -1017,3 +1017,14 @@ void ds_switch_to(struct task_struct *prev, struct task_struct *next) | |||
1017 | 1017 | ||
1018 | update_debugctlmsr(next->thread.debugctlmsr); | 1018 | update_debugctlmsr(next->thread.debugctlmsr); |
1019 | } | 1019 | } |
1020 | |||
1021 | void ds_copy_thread(struct task_struct *tsk, struct task_struct *father) | ||
1022 | { | ||
1023 | clear_tsk_thread_flag(tsk, TIF_DS_AREA_MSR); | ||
1024 | tsk->thread.ds_ctx = NULL; | ||
1025 | } | ||
1026 | |||
1027 | void ds_exit_thread(struct task_struct *tsk) | ||
1028 | { | ||
1029 | WARN_ON(tsk->thread.ds_ctx); | ||
1030 | } | ||
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index 82fb2809ce32..c4b5b24e0217 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c | |||
@@ -272,13 +272,18 @@ static struct attribute_group mc_attr_group = { | |||
272 | .name = "microcode", | 272 | .name = "microcode", |
273 | }; | 273 | }; |
274 | 274 | ||
275 | static void microcode_fini_cpu(int cpu) | 275 | static void __microcode_fini_cpu(int cpu) |
276 | { | 276 | { |
277 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 277 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
278 | 278 | ||
279 | mutex_lock(µcode_mutex); | ||
280 | microcode_ops->microcode_fini_cpu(cpu); | 279 | microcode_ops->microcode_fini_cpu(cpu); |
281 | uci->valid = 0; | 280 | uci->valid = 0; |
281 | } | ||
282 | |||
283 | static void microcode_fini_cpu(int cpu) | ||
284 | { | ||
285 | mutex_lock(µcode_mutex); | ||
286 | __microcode_fini_cpu(cpu); | ||
282 | mutex_unlock(µcode_mutex); | 287 | mutex_unlock(µcode_mutex); |
283 | } | 288 | } |
284 | 289 | ||
@@ -306,12 +311,16 @@ static int microcode_resume_cpu(int cpu) | |||
306 | * to this cpu (a bit of paranoia): | 311 | * to this cpu (a bit of paranoia): |
307 | */ | 312 | */ |
308 | if (microcode_ops->collect_cpu_info(cpu, &nsig)) { | 313 | if (microcode_ops->collect_cpu_info(cpu, &nsig)) { |
309 | microcode_fini_cpu(cpu); | 314 | __microcode_fini_cpu(cpu); |
315 | printk(KERN_ERR "failed to collect_cpu_info for resuming cpu #%d\n", | ||
316 | cpu); | ||
310 | return -1; | 317 | return -1; |
311 | } | 318 | } |
312 | 319 | ||
313 | if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) { | 320 | if ((nsig.sig != uci->cpu_sig.sig) || (nsig.pf != uci->cpu_sig.pf)) { |
314 | microcode_fini_cpu(cpu); | 321 | __microcode_fini_cpu(cpu); |
322 | printk(KERN_ERR "cached ucode doesn't match the resuming cpu #%d\n", | ||
323 | cpu); | ||
315 | /* Should we look for a new ucode here? */ | 324 | /* Should we look for a new ucode here? */ |
316 | return 1; | 325 | return 1; |
317 | } | 326 | } |
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 622dc4a21784..a8e62792d171 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c | |||
@@ -155,6 +155,7 @@ static DEFINE_SPINLOCK(microcode_update_lock); | |||
155 | static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | 155 | static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) |
156 | { | 156 | { |
157 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); | 157 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); |
158 | unsigned long flags; | ||
158 | unsigned int val[2]; | 159 | unsigned int val[2]; |
159 | 160 | ||
160 | memset(csig, 0, sizeof(*csig)); | 161 | memset(csig, 0, sizeof(*csig)); |
@@ -174,11 +175,16 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | |||
174 | csig->pf = 1 << ((val[1] >> 18) & 7); | 175 | csig->pf = 1 << ((val[1] >> 18) & 7); |
175 | } | 176 | } |
176 | 177 | ||
178 | /* serialize access to the physical write to MSR 0x79 */ | ||
179 | spin_lock_irqsave(µcode_update_lock, flags); | ||
180 | |||
177 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | 181 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); |
178 | /* see notes above for revision 1.07. Apparent chip bug */ | 182 | /* see notes above for revision 1.07. Apparent chip bug */ |
179 | sync_core(); | 183 | sync_core(); |
180 | /* get the current revision from MSR 0x8B */ | 184 | /* get the current revision from MSR 0x8B */ |
181 | rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev); | 185 | rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev); |
186 | spin_unlock_irqrestore(µcode_update_lock, flags); | ||
187 | |||
182 | pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", | 188 | pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", |
183 | csig->sig, csig->pf, csig->rev); | 189 | csig->sig, csig->pf, csig->rev); |
184 | 190 | ||
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index ba7ad83e20a8..a35eaa379ff6 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c | |||
@@ -745,10 +745,8 @@ void __init gart_iommu_init(void) | |||
745 | unsigned long scratch; | 745 | unsigned long scratch; |
746 | long i; | 746 | long i; |
747 | 747 | ||
748 | if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0) { | 748 | if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0) |
749 | printk(KERN_INFO "PCI-GART: No AMD GART found.\n"); | ||
750 | return; | 749 | return; |
751 | } | ||
752 | 750 | ||
753 | #ifndef CONFIG_AGP_AMD64 | 751 | #ifndef CONFIG_AGP_AMD64 |
754 | no_agp = 1; | 752 | no_agp = 1; |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 605eff9a8ac0..3ba155d24884 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include <asm/idle.h> | 60 | #include <asm/idle.h> |
61 | #include <asm/syscalls.h> | 61 | #include <asm/syscalls.h> |
62 | #include <asm/smp.h> | 62 | #include <asm/smp.h> |
63 | #include <asm/ds.h> | ||
63 | 64 | ||
64 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | 65 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); |
65 | 66 | ||
@@ -251,17 +252,8 @@ void exit_thread(void) | |||
251 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; | 252 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; |
252 | put_cpu(); | 253 | put_cpu(); |
253 | } | 254 | } |
254 | #ifdef CONFIG_X86_DS | 255 | |
255 | /* Free any BTS tracers that have not been properly released. */ | 256 | ds_exit_thread(current); |
256 | if (unlikely(current->bts)) { | ||
257 | ds_release_bts(current->bts); | ||
258 | current->bts = NULL; | ||
259 | |||
260 | kfree(current->bts_buffer); | ||
261 | current->bts_buffer = NULL; | ||
262 | current->bts_size = 0; | ||
263 | } | ||
264 | #endif /* CONFIG_X86_DS */ | ||
265 | } | 257 | } |
266 | 258 | ||
267 | void flush_thread(void) | 259 | void flush_thread(void) |
@@ -343,6 +335,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, | |||
343 | kfree(p->thread.io_bitmap_ptr); | 335 | kfree(p->thread.io_bitmap_ptr); |
344 | p->thread.io_bitmap_max = 0; | 336 | p->thread.io_bitmap_max = 0; |
345 | } | 337 | } |
338 | |||
339 | ds_copy_thread(p, current); | ||
340 | |||
341 | clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR); | ||
342 | p->thread.debugctlmsr = 0; | ||
343 | |||
346 | return err; | 344 | return err; |
347 | } | 345 | } |
348 | 346 | ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 1cfd2a4bf853..416fb9282f4f 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <asm/ia32.h> | 53 | #include <asm/ia32.h> |
54 | #include <asm/idle.h> | 54 | #include <asm/idle.h> |
55 | #include <asm/syscalls.h> | 55 | #include <asm/syscalls.h> |
56 | #include <asm/ds.h> | ||
56 | 57 | ||
57 | asmlinkage extern void ret_from_fork(void); | 58 | asmlinkage extern void ret_from_fork(void); |
58 | 59 | ||
@@ -236,17 +237,8 @@ void exit_thread(void) | |||
236 | t->io_bitmap_max = 0; | 237 | t->io_bitmap_max = 0; |
237 | put_cpu(); | 238 | put_cpu(); |
238 | } | 239 | } |
239 | #ifdef CONFIG_X86_DS | 240 | |
240 | /* Free any BTS tracers that have not been properly released. */ | 241 | ds_exit_thread(current); |
241 | if (unlikely(current->bts)) { | ||
242 | ds_release_bts(current->bts); | ||
243 | current->bts = NULL; | ||
244 | |||
245 | kfree(current->bts_buffer); | ||
246 | current->bts_buffer = NULL; | ||
247 | current->bts_size = 0; | ||
248 | } | ||
249 | #endif /* CONFIG_X86_DS */ | ||
250 | } | 242 | } |
251 | 243 | ||
252 | void flush_thread(void) | 244 | void flush_thread(void) |
@@ -376,6 +368,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, | |||
376 | if (err) | 368 | if (err) |
377 | goto out; | 369 | goto out; |
378 | } | 370 | } |
371 | |||
372 | ds_copy_thread(p, me); | ||
373 | |||
374 | clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR); | ||
375 | p->thread.debugctlmsr = 0; | ||
376 | |||
379 | err = 0; | 377 | err = 0; |
380 | out: | 378 | out: |
381 | if (err && p->thread.io_bitmap_ptr) { | 379 | if (err && p->thread.io_bitmap_ptr) { |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 45e9855da2d2..0a5df5f82fb9 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -650,6 +650,24 @@ static int ptrace_bts_drain(struct task_struct *child, | |||
650 | return drained; | 650 | return drained; |
651 | } | 651 | } |
652 | 652 | ||
653 | static int ptrace_bts_allocate_buffer(struct task_struct *child, size_t size) | ||
654 | { | ||
655 | child->bts_buffer = alloc_locked_buffer(size); | ||
656 | if (!child->bts_buffer) | ||
657 | return -ENOMEM; | ||
658 | |||
659 | child->bts_size = size; | ||
660 | |||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static void ptrace_bts_free_buffer(struct task_struct *child) | ||
665 | { | ||
666 | free_locked_buffer(child->bts_buffer, child->bts_size); | ||
667 | child->bts_buffer = NULL; | ||
668 | child->bts_size = 0; | ||
669 | } | ||
670 | |||
653 | static int ptrace_bts_config(struct task_struct *child, | 671 | static int ptrace_bts_config(struct task_struct *child, |
654 | long cfg_size, | 672 | long cfg_size, |
655 | const struct ptrace_bts_config __user *ucfg) | 673 | const struct ptrace_bts_config __user *ucfg) |
@@ -679,14 +697,13 @@ static int ptrace_bts_config(struct task_struct *child, | |||
679 | 697 | ||
680 | if ((cfg.flags & PTRACE_BTS_O_ALLOC) && | 698 | if ((cfg.flags & PTRACE_BTS_O_ALLOC) && |
681 | (cfg.size != child->bts_size)) { | 699 | (cfg.size != child->bts_size)) { |
682 | kfree(child->bts_buffer); | 700 | int error; |
683 | 701 | ||
684 | child->bts_size = cfg.size; | 702 | ptrace_bts_free_buffer(child); |
685 | child->bts_buffer = kzalloc(cfg.size, GFP_KERNEL); | 703 | |
686 | if (!child->bts_buffer) { | 704 | error = ptrace_bts_allocate_buffer(child, cfg.size); |
687 | child->bts_size = 0; | 705 | if (error < 0) |
688 | return -ENOMEM; | 706 | return error; |
689 | } | ||
690 | } | 707 | } |
691 | 708 | ||
692 | if (cfg.flags & PTRACE_BTS_O_TRACE) | 709 | if (cfg.flags & PTRACE_BTS_O_TRACE) |
@@ -701,10 +718,8 @@ static int ptrace_bts_config(struct task_struct *child, | |||
701 | if (IS_ERR(child->bts)) { | 718 | if (IS_ERR(child->bts)) { |
702 | int error = PTR_ERR(child->bts); | 719 | int error = PTR_ERR(child->bts); |
703 | 720 | ||
704 | kfree(child->bts_buffer); | 721 | ptrace_bts_free_buffer(child); |
705 | child->bts = NULL; | 722 | child->bts = NULL; |
706 | child->bts_buffer = NULL; | ||
707 | child->bts_size = 0; | ||
708 | 723 | ||
709 | return error; | 724 | return error; |
710 | } | 725 | } |
@@ -769,8 +784,55 @@ static int ptrace_bts_size(struct task_struct *child) | |||
769 | 784 | ||
770 | return (trace->ds.top - trace->ds.begin) / trace->ds.size; | 785 | return (trace->ds.top - trace->ds.begin) / trace->ds.size; |
771 | } | 786 | } |
787 | |||
788 | static void ptrace_bts_fork(struct task_struct *tsk) | ||
789 | { | ||
790 | tsk->bts = NULL; | ||
791 | tsk->bts_buffer = NULL; | ||
792 | tsk->bts_size = 0; | ||
793 | tsk->thread.bts_ovfl_signal = 0; | ||
794 | } | ||
795 | |||
796 | static void ptrace_bts_untrace(struct task_struct *child) | ||
797 | { | ||
798 | if (unlikely(child->bts)) { | ||
799 | ds_release_bts(child->bts); | ||
800 | child->bts = NULL; | ||
801 | |||
802 | /* We cannot update total_vm and locked_vm since | ||
803 | child's mm is already gone. But we can reclaim the | ||
804 | memory. */ | ||
805 | kfree(child->bts_buffer); | ||
806 | child->bts_buffer = NULL; | ||
807 | child->bts_size = 0; | ||
808 | } | ||
809 | } | ||
810 | |||
811 | static void ptrace_bts_detach(struct task_struct *child) | ||
812 | { | ||
813 | if (unlikely(child->bts)) { | ||
814 | ds_release_bts(child->bts); | ||
815 | child->bts = NULL; | ||
816 | |||
817 | ptrace_bts_free_buffer(child); | ||
818 | } | ||
819 | } | ||
820 | #else | ||
821 | static inline void ptrace_bts_fork(struct task_struct *tsk) {} | ||
822 | static inline void ptrace_bts_detach(struct task_struct *child) {} | ||
823 | static inline void ptrace_bts_untrace(struct task_struct *child) {} | ||
772 | #endif /* CONFIG_X86_PTRACE_BTS */ | 824 | #endif /* CONFIG_X86_PTRACE_BTS */ |
773 | 825 | ||
826 | void x86_ptrace_fork(struct task_struct *child, unsigned long clone_flags) | ||
827 | { | ||
828 | ptrace_bts_fork(child); | ||
829 | } | ||
830 | |||
831 | void x86_ptrace_untrace(struct task_struct *child) | ||
832 | { | ||
833 | ptrace_bts_untrace(child); | ||
834 | } | ||
835 | |||
774 | /* | 836 | /* |
775 | * Called by kernel/ptrace.c when detaching.. | 837 | * Called by kernel/ptrace.c when detaching.. |
776 | * | 838 | * |
@@ -782,16 +844,7 @@ void ptrace_disable(struct task_struct *child) | |||
782 | #ifdef TIF_SYSCALL_EMU | 844 | #ifdef TIF_SYSCALL_EMU |
783 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); | 845 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); |
784 | #endif | 846 | #endif |
785 | #ifdef CONFIG_X86_PTRACE_BTS | 847 | ptrace_bts_detach(child); |
786 | if (child->bts) { | ||
787 | ds_release_bts(child->bts); | ||
788 | child->bts = NULL; | ||
789 | |||
790 | kfree(child->bts_buffer); | ||
791 | child->bts_buffer = NULL; | ||
792 | child->bts_size = 0; | ||
793 | } | ||
794 | #endif /* CONFIG_X86_PTRACE_BTS */ | ||
795 | } | 848 | } |
796 | 849 | ||
797 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | 850 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f71f96fc9e62..f6174d229024 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -287,7 +287,7 @@ static int __cpuinitdata unsafe_smp; | |||
287 | /* | 287 | /* |
288 | * Activate a secondary processor. | 288 | * Activate a secondary processor. |
289 | */ | 289 | */ |
290 | static void __cpuinit start_secondary(void *unused) | 290 | notrace static void __cpuinit start_secondary(void *unused) |
291 | { | 291 | { |
292 | /* | 292 | /* |
293 | * Don't put *anything* before cpu_init(), SMP booting is too | 293 | * Don't put *anything* before cpu_init(), SMP booting is too |