aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/kernel/sys_sparc.c90
1 files changed, 68 insertions, 22 deletions
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 5f8c822a2b4a..095db723bb8a 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -33,14 +33,55 @@
33 33
34/* #define DEBUG_UNIMP_SYSCALL */ 34/* #define DEBUG_UNIMP_SYSCALL */
35 35
36/* XXX Make this per-binary type, this way we can detect the type of
37 * XXX a binary. Every Sparc executable calls this very early on.
38 */
39asmlinkage unsigned long sys_getpagesize(void) 36asmlinkage unsigned long sys_getpagesize(void)
40{ 37{
41 return PAGE_SIZE; 38 return PAGE_SIZE;
42} 39}
43 40
41#define VA_EXCLUDE_START (0x0000080000000000UL - (1UL << 32UL))
42#define VA_EXCLUDE_END (0xfffff80000000000UL + (1UL << 32UL))
43
44/* Does addr --> addr+len fall within 4GB of the VA-space hole or
45 * overflow past the end of the 64-bit address space?
46 */
47static inline int invalid_64bit_range(unsigned long addr, unsigned long len)
48{
49 unsigned long va_exclude_start, va_exclude_end;
50
51 va_exclude_start = VA_EXCLUDE_START;
52 va_exclude_end = VA_EXCLUDE_END;
53
54 if (unlikely(len >= va_exclude_start))
55 return 1;
56
57 if (unlikely((addr + len) < addr))
58 return 1;
59
60 if (unlikely((addr >= va_exclude_start && addr < va_exclude_end) ||
61 ((addr + len) >= va_exclude_start &&
62 (addr + len) < va_exclude_end)))
63 return 1;
64
65 return 0;
66}
67
68/* Does start,end straddle the VA-space hole? */
69static inline int straddles_64bit_va_hole(unsigned long start, unsigned long end)
70{
71 unsigned long va_exclude_start, va_exclude_end;
72
73 va_exclude_start = VA_EXCLUDE_START;
74 va_exclude_end = VA_EXCLUDE_END;
75
76 if (likely(start < va_exclude_start && end < va_exclude_start))
77 return 0;
78
79 if (likely(start >= va_exclude_end && end >= va_exclude_end))
80 return 0;
81
82 return 1;
83}
84
44#define COLOUR_ALIGN(addr,pgoff) \ 85#define COLOUR_ALIGN(addr,pgoff) \
45 ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \ 86 ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \
46 (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1))) 87 (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
@@ -65,7 +106,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
65 106
66 if (test_thread_flag(TIF_32BIT)) 107 if (test_thread_flag(TIF_32BIT))
67 task_size = 0xf0000000UL; 108 task_size = 0xf0000000UL;
68 if (len > task_size || len > -PAGE_OFFSET) 109 if (len > task_size || len >= VA_EXCLUDE_START)
69 return -ENOMEM; 110 return -ENOMEM;
70 111
71 do_color_align = 0; 112 do_color_align = 0;
@@ -100,9 +141,10 @@ full_search:
100 141
101 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { 142 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
102 /* At this point: (!vma || addr < vma->vm_end). */ 143 /* At this point: (!vma || addr < vma->vm_end). */
103 if (addr < PAGE_OFFSET && -PAGE_OFFSET - len < addr) { 144 if (addr < VA_EXCLUDE_START &&
104 addr = PAGE_OFFSET; 145 (addr + len) >= VA_EXCLUDE_START) {
105 vma = find_vma(mm, PAGE_OFFSET); 146 addr = VA_EXCLUDE_END;
147 vma = find_vma(mm, VA_EXCLUDE_END);
106 } 148 }
107 if (task_size < addr) { 149 if (task_size < addr) {
108 if (start_addr != TASK_UNMAPPED_BASE) { 150 if (start_addr != TASK_UNMAPPED_BASE) {
@@ -174,12 +216,12 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u
174asmlinkage unsigned long sparc_brk(unsigned long brk) 216asmlinkage unsigned long sparc_brk(unsigned long brk)
175{ 217{
176 /* People could try to be nasty and use ta 0x6d in 32bit programs */ 218 /* People could try to be nasty and use ta 0x6d in 32bit programs */
177 if (test_thread_flag(TIF_32BIT) && 219 if (test_thread_flag(TIF_32BIT) && brk >= 0xf0000000UL)
178 brk >= 0xf0000000UL)
179 return current->mm->brk; 220 return current->mm->brk;
180 221
181 if ((current->mm->brk & PAGE_OFFSET) != (brk & PAGE_OFFSET)) 222 if (unlikely(straddles_64bit_va_hole(current->mm->brk, brk)))
182 return current->mm->brk; 223 return current->mm->brk;
224
183 return sys_brk(brk); 225 return sys_brk(brk);
184} 226}
185 227
@@ -340,13 +382,16 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
340 retval = -EINVAL; 382 retval = -EINVAL;
341 383
342 if (test_thread_flag(TIF_32BIT)) { 384 if (test_thread_flag(TIF_32BIT)) {
343 if (len > 0xf0000000UL || 385 if (len >= 0xf0000000UL)
344 ((flags & MAP_FIXED) && addr > 0xf0000000UL - len)) 386 goto out_putf;
387
388 if ((flags & MAP_FIXED) && addr > 0xf0000000UL - len)
345 goto out_putf; 389 goto out_putf;
346 } else { 390 } else {
347 if (len > -PAGE_OFFSET || 391 if (len >= VA_EXCLUDE_START)
348 ((flags & MAP_FIXED) && 392 goto out_putf;
349 addr < PAGE_OFFSET && addr + len > -PAGE_OFFSET)) 393
394 if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len))
350 goto out_putf; 395 goto out_putf;
351 } 396 }
352 397
@@ -365,9 +410,9 @@ asmlinkage long sys64_munmap(unsigned long addr, size_t len)
365{ 410{
366 long ret; 411 long ret;
367 412
368 if (len > -PAGE_OFFSET || 413 if (invalid_64bit_range(addr, len))
369 (addr < PAGE_OFFSET && addr + len > -PAGE_OFFSET))
370 return -EINVAL; 414 return -EINVAL;
415
371 down_write(&current->mm->mmap_sem); 416 down_write(&current->mm->mmap_sem);
372 ret = do_munmap(current->mm, addr, len); 417 ret = do_munmap(current->mm, addr, len);
373 up_write(&current->mm->mmap_sem); 418 up_write(&current->mm->mmap_sem);
@@ -384,18 +429,19 @@ asmlinkage unsigned long sys64_mremap(unsigned long addr,
384{ 429{
385 struct vm_area_struct *vma; 430 struct vm_area_struct *vma;
386 unsigned long ret = -EINVAL; 431 unsigned long ret = -EINVAL;
432
387 if (test_thread_flag(TIF_32BIT)) 433 if (test_thread_flag(TIF_32BIT))
388 goto out; 434 goto out;
389 if (old_len > -PAGE_OFFSET || new_len > -PAGE_OFFSET) 435 if (unlikely(new_len >= VA_EXCLUDE_START))
390 goto out; 436 goto out;
391 if (addr < PAGE_OFFSET && addr + old_len > -PAGE_OFFSET) 437 if (unlikely(invalid_64bit_range(addr, old_len)))
392 goto out; 438 goto out;
439
393 down_write(&current->mm->mmap_sem); 440 down_write(&current->mm->mmap_sem);
394 if (flags & MREMAP_FIXED) { 441 if (flags & MREMAP_FIXED) {
395 if (new_addr < PAGE_OFFSET && 442 if (invalid_64bit_range(new_addr, new_len))
396 new_addr + new_len > -PAGE_OFFSET)
397 goto out_sem; 443 goto out_sem;
398 } else if (addr < PAGE_OFFSET && addr + new_len > -PAGE_OFFSET) { 444 } else if (invalid_64bit_range(addr, new_len)) {
399 unsigned long map_flags = 0; 445 unsigned long map_flags = 0;
400 struct file *file = NULL; 446 struct file *file = NULL;
401 447