diff options
author | David Daney <ddaney@caviumnetworks.com> | 2010-10-14 14:32:33 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2010-10-29 14:08:53 -0400 |
commit | 949e51bea342da838be5295628e4a7ada8bae833 (patch) | |
tree | 8967391768d4da3a99a2adf85e0834e0fa7a2009 /arch/mips | |
parent | 18d693b3598fdebdd5c65a613221793456a7ce45 (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.h | 4 | ||||
-rw-r--r-- | arch/mips/include/asm/processor.h | 40 | ||||
-rw-r--r-- | arch/mips/include/asm/uaccess.h | 4 | ||||
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 13 |
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) | 38 | extern 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 */ | ||
994 | u64 __ua_limit; | ||
995 | EXPORT_SYMBOL(__ua_limit); | ||
996 | #endif | ||
997 | |||
990 | const char *__cpu_name[NR_CPUS]; | 998 | const char *__cpu_name[NR_CPUS]; |
991 | const char *__elf_platform; | 999 | const 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) |