aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2010-10-14 14:32:33 -0400
committerRalf Baechle <ralf@linux-mips.org>2010-10-29 14:08:53 -0400
commit949e51bea342da838be5295628e4a7ada8bae833 (patch)
tree8967391768d4da3a99a2adf85e0834e0fa7a2009 /arch/mips
parent18d693b3598fdebdd5c65a613221793456a7ce45 (diff)
MIPS: Make TASK_SIZE reflect proper size for both 32 and 64 bit processes.
The TASK_SIZE macro should reflect the size of a user process virtual address space. Previously for 64-bit kernels, this was not the case. The immediate cause of pain was in hugetlbfs/inode.c:hugetlb_get_unmapped_area() where 32-bit processes trying to mmap a huge page would be served a page with an address outside of the 32-bit address range. But there are other uses of TASK_SIZE in the kernel as well that would like an accurate value. The new definition is nice because it now makes TASK_SIZE and TASK_SIZE_OF() yield the same value for any given process. For 32-bit kernels there should be no change, although I did factor out some code in asm/processor.h that became identical for the 32-bit and 64-bit cases. __UA_LIMIT is now set to ~((1 << SEGBITS) - 1) for 64-bit kernels. This should eliminate the possibility of getting a AddressErrorException in the kernel for addresses that pass the access_ok() test. With the patch applied, I can still run o32, n32 and n64 processes, and have an o32 shell fork/exec both n32 and n64 processes. Signed-off-by: David Daney <ddaney@caviumnetworks.com> To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1701/
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/include/asm/pgtable-64.h4
-rw-r--r--arch/mips/include/asm/processor.h40
-rw-r--r--arch/mips/include/asm/uaccess.h4
-rw-r--r--arch/mips/kernel/cpu-probe.c13
4 files changed, 37 insertions, 24 deletions
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h
index f00896087dda..55908fd56b1f 100644
--- a/arch/mips/include/asm/pgtable-64.h
+++ b/arch/mips/include/asm/pgtable-64.h
@@ -113,10 +113,10 @@
113#endif 113#endif
114#define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t)) 114#define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
115 115
116#if PGDIR_SIZE >= TASK_SIZE 116#if PGDIR_SIZE >= TASK_SIZE64
117#define USER_PTRS_PER_PGD (1) 117#define USER_PTRS_PER_PGD (1)
118#else 118#else
119#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) 119#define USER_PTRS_PER_PGD (TASK_SIZE64 / PGDIR_SIZE)
120#endif 120#endif
121#define FIRST_USER_ADDRESS 0UL 121#define FIRST_USER_ADDRESS 0UL
122 122
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 0d629bb93cbe..ead6928fa6b8 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -50,13 +50,10 @@ extern unsigned int vced_count, vcei_count;
50 * so don't change it unless you know what you are doing. 50 * so don't change it unless you know what you are doing.
51 */ 51 */
52#define TASK_SIZE 0x7fff8000UL 52#define TASK_SIZE 0x7fff8000UL
53#define STACK_TOP ((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE)
54 53
55/* 54#ifdef __KERNEL__
56 * This decides where the kernel will search for a free chunk of vm 55#define STACK_TOP_MAX TASK_SIZE
57 * space during mmap's. 56#endif
58 */
59#define TASK_UNMAPPED_BASE ((TASK_SIZE / 3) & ~(PAGE_SIZE))
60 57
61#define TASK_IS_32BIT_ADDR 1 58#define TASK_IS_32BIT_ADDR 1
62 59
@@ -71,28 +68,29 @@ extern unsigned int vced_count, vcei_count;
71 * 8192EB ... 68 * 8192EB ...
72 */ 69 */
73#define TASK_SIZE32 0x7fff8000UL 70#define TASK_SIZE32 0x7fff8000UL
74#define TASK_SIZE 0x10000000000UL 71#define TASK_SIZE64 0x10000000000UL
75#define STACK_TOP \ 72#define TASK_SIZE (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64)
76 (((test_thread_flag(TIF_32BIT_ADDR) ? \ 73
77 TASK_SIZE32 : TASK_SIZE) & PAGE_MASK) - SPECIAL_PAGES_SIZE) 74#ifdef __KERNEL__
75#define STACK_TOP_MAX TASK_SIZE64
76#endif
77
78 78
79/*
80 * This decides where the kernel will search for a free chunk of vm
81 * space during mmap's.
82 */
83#define TASK_UNMAPPED_BASE \
84 (test_thread_flag(TIF_32BIT_ADDR) ? \
85 PAGE_ALIGN(TASK_SIZE32 / 3) : PAGE_ALIGN(TASK_SIZE / 3))
86#define TASK_SIZE_OF(tsk) \ 79#define TASK_SIZE_OF(tsk) \
87 (test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE) 80 (test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64)
88 81
89#define TASK_IS_32BIT_ADDR test_thread_flag(TIF_32BIT_ADDR) 82#define TASK_IS_32BIT_ADDR test_thread_flag(TIF_32BIT_ADDR)
90 83
91#endif 84#endif
92 85
93#ifdef __KERNEL__ 86#define STACK_TOP ((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE)
94#define STACK_TOP_MAX TASK_SIZE 87
95#endif 88/*
89 * This decides where the kernel will search for a free chunk of vm
90 * space during mmap's.
91 */
92#define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3)
93
96 94
97#define NUM_FPU_REGS 32 95#define NUM_FPU_REGS 32
98 96
diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
index c2d53c18fd36..653a412c036c 100644
--- a/arch/mips/include/asm/uaccess.h
+++ b/arch/mips/include/asm/uaccess.h
@@ -35,7 +35,9 @@
35 35
36#ifdef CONFIG_64BIT 36#ifdef CONFIG_64BIT
37 37
38#define __UA_LIMIT (- TASK_SIZE) 38extern u64 __ua_limit;
39
40#define __UA_LIMIT __ua_limit
39 41
40#define __UA_ADDR ".dword" 42#define __UA_ADDR ".dword"
41#define __UA_LA "dla" 43#define __UA_LA "dla"
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index f7faa3fb79b2..71620e19827a 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -25,6 +25,8 @@
25#include <asm/system.h> 25#include <asm/system.h>
26#include <asm/watch.h> 26#include <asm/watch.h>
27#include <asm/spram.h> 27#include <asm/spram.h>
28#include <asm/uaccess.h>
29
28/* 30/*
29 * Not all of the MIPS CPUs have the "wait" instruction available. Moreover, 31 * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
30 * the implementation of the "wait" feature differs between CPU families. This 32 * the implementation of the "wait" feature differs between CPU families. This
@@ -987,6 +989,12 @@ static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
987 } 989 }
988} 990}
989 991
992#ifdef CONFIG_64BIT
993/* For use by uaccess.h */
994u64 __ua_limit;
995EXPORT_SYMBOL(__ua_limit);
996#endif
997
990const char *__cpu_name[NR_CPUS]; 998const char *__cpu_name[NR_CPUS];
991const char *__elf_platform; 999const char *__elf_platform;
992 1000
@@ -1064,6 +1072,11 @@ __cpuinit void cpu_probe(void)
1064 c->srsets = 1; 1072 c->srsets = 1;
1065 1073
1066 cpu_probe_vmbits(c); 1074 cpu_probe_vmbits(c);
1075
1076#ifdef CONFIG_64BIT
1077 if (cpu == 0)
1078 __ua_limit = ~((1ull << cpu_vmbits) - 1);
1079#endif
1067} 1080}
1068 1081
1069__cpuinit void cpu_report(void) 1082__cpuinit void cpu_report(void)