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/
This commit is contained in:
		
							parent
							
								
									18d693b359
								
							
						
					
					
						commit
						949e51bea3
					
				| @ -113,10 +113,10 @@ | ||||
| #endif | ||||
| #define PTRS_PER_PTE	((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t)) | ||||
| 
 | ||||
| #if PGDIR_SIZE >= TASK_SIZE | ||||
| #if PGDIR_SIZE >= TASK_SIZE64 | ||||
| #define USER_PTRS_PER_PGD       (1) | ||||
| #else | ||||
| #define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE) | ||||
| #define USER_PTRS_PER_PGD	(TASK_SIZE64 / PGDIR_SIZE) | ||||
| #endif | ||||
| #define FIRST_USER_ADDRESS	0UL | ||||
| 
 | ||||
|  | ||||
| @ -50,13 +50,10 @@ extern unsigned int vced_count, vcei_count; | ||||
|  * so don't change it unless you know what you are doing. | ||||
|  */ | ||||
| #define TASK_SIZE	0x7fff8000UL | ||||
| #define STACK_TOP	((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE) | ||||
| 
 | ||||
| /*
 | ||||
|  * This decides where the kernel will search for a free chunk of vm | ||||
|  * space during mmap's. | ||||
|  */ | ||||
| #define TASK_UNMAPPED_BASE	((TASK_SIZE / 3) & ~(PAGE_SIZE)) | ||||
| #ifdef __KERNEL__ | ||||
| #define STACK_TOP_MAX	TASK_SIZE | ||||
| #endif | ||||
| 
 | ||||
| #define TASK_IS_32BIT_ADDR 1 | ||||
| 
 | ||||
| @ -71,28 +68,29 @@ extern unsigned int vced_count, vcei_count; | ||||
|  * 8192EB ... | ||||
|  */ | ||||
| #define TASK_SIZE32	0x7fff8000UL | ||||
| #define TASK_SIZE	0x10000000000UL | ||||
| #define STACK_TOP	\ | ||||
| 	(((test_thread_flag(TIF_32BIT_ADDR) ?				\ | ||||
| 	   TASK_SIZE32 : TASK_SIZE) & PAGE_MASK) - SPECIAL_PAGES_SIZE) | ||||
| #define TASK_SIZE64	0x10000000000UL | ||||
| #define TASK_SIZE (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64) | ||||
| 
 | ||||
| #ifdef __KERNEL__ | ||||
| #define STACK_TOP_MAX	TASK_SIZE64 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * This decides where the kernel will search for a free chunk of vm | ||||
|  * space during mmap's. | ||||
|  */ | ||||
| #define TASK_UNMAPPED_BASE						\ | ||||
| 	(test_thread_flag(TIF_32BIT_ADDR) ?				\ | ||||
| 		PAGE_ALIGN(TASK_SIZE32 / 3) : PAGE_ALIGN(TASK_SIZE / 3)) | ||||
| #define TASK_SIZE_OF(tsk)						\ | ||||
| 	(test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE) | ||||
| 	(test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64) | ||||
| 
 | ||||
| #define TASK_IS_32BIT_ADDR test_thread_flag(TIF_32BIT_ADDR) | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __KERNEL__ | ||||
| #define STACK_TOP_MAX	TASK_SIZE | ||||
| #endif | ||||
| #define STACK_TOP	((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE) | ||||
| 
 | ||||
| /*
 | ||||
|  * This decides where the kernel will search for a free chunk of vm | ||||
|  * space during mmap's. | ||||
|  */ | ||||
| #define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3) | ||||
| 
 | ||||
| 
 | ||||
| #define NUM_FPU_REGS	32 | ||||
| 
 | ||||
|  | ||||
| @ -35,7 +35,9 @@ | ||||
| 
 | ||||
| #ifdef CONFIG_64BIT | ||||
| 
 | ||||
| #define __UA_LIMIT	(- TASK_SIZE) | ||||
| extern u64 __ua_limit; | ||||
| 
 | ||||
| #define __UA_LIMIT	__ua_limit | ||||
| 
 | ||||
| #define __UA_ADDR	".dword" | ||||
| #define __UA_LA		"dla" | ||||
|  | ||||
| @ -25,6 +25,8 @@ | ||||
| #include <asm/system.h> | ||||
| #include <asm/watch.h> | ||||
| #include <asm/spram.h> | ||||
| #include <asm/uaccess.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * Not all of the MIPS CPUs have the "wait" instruction available. Moreover, | ||||
|  * 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) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_64BIT | ||||
| /* For use by uaccess.h */ | ||||
| u64 __ua_limit; | ||||
| EXPORT_SYMBOL(__ua_limit); | ||||
| #endif | ||||
| 
 | ||||
| const char *__cpu_name[NR_CPUS]; | ||||
| const char *__elf_platform; | ||||
| 
 | ||||
| @ -1064,6 +1072,11 @@ __cpuinit void cpu_probe(void) | ||||
| 		c->srsets = 1; | ||||
| 
 | ||||
| 	cpu_probe_vmbits(c); | ||||
| 
 | ||||
| #ifdef CONFIG_64BIT | ||||
| 	if (cpu == 0) | ||||
| 		__ua_limit = ~((1ull << cpu_vmbits) - 1); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| __cpuinit void cpu_report(void) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user