diff options
author | Greg Ungerer <gerg@snapgear.com> | 2009-05-20 02:12:32 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2009-05-20 13:53:14 -0400 |
commit | a5e696e5d0f1377ff6beb10d2f40edb6a3d1de18 (patch) | |
tree | 2f7b194c53e9a7e2ab6c8b58335c299a897231fe /arch/mips/mm/tlb-r4k.c | |
parent | 195d1a96ae5fdfbedb8dc4b97afee578921fa99e (diff) |
MIPS: 64-bit: Fix system lockup.
The address range size calculation inside local_flush_tlb_kernel_range()
is being truncated by a too small size variable holder on 64-bit systems.
The truncated size can result in an erroneous tlbsize check that means we
sit spinning inside a loop trying to flush a hige number of TLB entries.
This is for all intents and purposes a system hang. Fix by using an
appropriately sized valiable to hold the size.
[Ralf: Greg's original patch submission identified the issue and fixed one
instance in tlb-r4k.c but there there were several more. For consistency
I also modified tlb-r3k.c even though that file is only used on 32-bit.]
Signed-off-by: Greg Ungerer <gerg@snapgear.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mm/tlb-r4k.c')
-rw-r--r-- | arch/mips/mm/tlb-r4k.c | 6 |
1 files changed, 2 insertions, 4 deletions
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 9619f66e531e..892be426787c 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c | |||
@@ -117,8 +117,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
117 | int cpu = smp_processor_id(); | 117 | int cpu = smp_processor_id(); |
118 | 118 | ||
119 | if (cpu_context(cpu, mm) != 0) { | 119 | if (cpu_context(cpu, mm) != 0) { |
120 | unsigned long flags; | 120 | unsigned long size, flags; |
121 | int size; | ||
122 | 121 | ||
123 | ENTER_CRITICAL(flags); | 122 | ENTER_CRITICAL(flags); |
124 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | 123 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; |
@@ -160,8 +159,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
160 | 159 | ||
161 | void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | 160 | void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) |
162 | { | 161 | { |
163 | unsigned long flags; | 162 | unsigned long size, flags; |
164 | int size; | ||
165 | 163 | ||
166 | ENTER_CRITICAL(flags); | 164 | ENTER_CRITICAL(flags); |
167 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | 165 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; |