aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/traps.c
diff options
context:
space:
mode:
authorMaksim Rayskiy <maksim.rayskiy@gmail.com>2011-11-10 12:59:45 -0500
committerRalf Baechle <ralf@linux-mips.org>2011-11-10 12:59:45 -0500
commit5c200197130e307de6eba72fc335c83c9dd6a5bc (patch)
treef633ada1e41c893822f4075dcfea0ae2d36deb0a /arch/mips/kernel/traps.c
parentb2f909419b72cf043814bf17b96c93d4695378a1 (diff)
MIPS: ASID conflict after CPU hotplug
I am running SMP Linux 2.6.37-rc1 on BMIPS5000 (single core dual thread) and observe some abnormalities when doing system suspend/resume which I narrowed down to cpu hotplugging. The suspend brings the second thread processor down and then restarts it, after which I see memory corruption in userspace. I started digging and found out that problem occurs because while doing execve() the child process is getting the same ASID as the parent, which obviously corrupts parent's address space. Further digging showed that activate_mm() calls get_new_mmu_context() to get a new ASID, but at this time ASID field in entryHi is 1, and asid_cache(cpu) is 0x100 (it was just reset to ASID_FIRST_VERSION when the secondary TP was booting). So, get_new_mmu_context() increments the asid_cache(cpu) value to 0x101, and thus puts 0x01 into entryHi. The result - ASID field does not get changed as it was supposed to. My solution is very simple - do not reset asid_cache(cpu) on TP warm restart. Patchwork: https://patchwork.linux-mips.org/patch/1797/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r--arch/mips/kernel/traps.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 261ccbc07740..5c8a49d55054 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1596,7 +1596,8 @@ void __cpuinit per_cpu_trap_init(void)
1596 } 1596 }
1597#endif /* CONFIG_MIPS_MT_SMTC */ 1597#endif /* CONFIG_MIPS_MT_SMTC */
1598 1598
1599 cpu_data[cpu].asid_cache = ASID_FIRST_VERSION; 1599 if (!cpu_data[cpu].asid_cache)
1600 cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
1600 1601
1601 atomic_inc(&init_mm.mm_count); 1602 atomic_inc(&init_mm.mm_count);
1602 current->active_mm = &init_mm; 1603 current->active_mm = &init_mm;