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 |
