Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 949e51be authored by David Daney's avatar David Daney Committed by Ralf Baechle
Browse files

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: default avatarDavid Daney <ddaney@caviumnetworks.com>
To: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/1701/
parent 18d693b3
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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

+19 −21
Original line number Diff line number Diff line
@@ -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

+3 −1
Original line number Diff line number Diff line
@@ -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"
+13 −0
Original line number Diff line number Diff line
@@ -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)