Skip to content

Commit

Permalink
MIPS: Optimise non-EVA kernel user memory accesses
Browse files Browse the repository at this point in the history
Commits ac1d859 (MIPS: asm: uaccess: Use EVA instructions
wrappers), 05c6516 (MIPS: asm: uaccess: Add EVA support to
copy_{in, to,from}_user) & e3a9b07 (MIPS: asm: uaccess: Add EVA
support for str*_user operations) added checks to various user memory
access functions & macros in order to determine whether to perform
standard memory accesses or their EVA userspace equivalents. In kernels
built without support for EVA these checks are entirely redundant. Avoid
emitting them & allow the compiler to optimise out the EVA userspace
code in such kernels by checking config_enabled(CONFIG_EVA).

This reduces the size of a malta_defconfig kernel built using GCC 4.9.2
by approximately 33KB (from 5995072 to 5962304 bytes).

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Markos Chandras <markos.chandras@imgtec.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
Patchwork: http://patchwork.linux-mips.org/patch/10165/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Paul Burton authored and Ralf Baechle committed Jun 21, 2015
1 parent df115f3 commit 1206066
Showing 1 changed file with 31 additions and 16 deletions.
47 changes: 31 additions & 16 deletions arch/mips/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@ extern u64 __ua_limit;

#define segment_eq(a, b) ((a).seg == (b).seg)

/*
* eva_kernel_access() - determine whether kernel memory access on an EVA system
*
* Determines whether memory accesses should be performed to kernel memory
* on a system using Extended Virtual Addressing (EVA).
*
* Return: true if a kernel memory access on an EVA system, else false.
*/
static inline bool eva_kernel_access(void)
{
if (!config_enabled(CONFIG_EVA))
return false;

return segment_eq(get_fs(), get_ds());
}

/*
* Is a address valid? This does a straighforward calculation rather
Expand Down Expand Up @@ -281,7 +296,7 @@ do { \
({ \
int __gu_err; \
\
if (segment_eq(get_fs(), get_ds())) { \
if (eva_kernel_access()) { \
__get_kernel_common((x), size, ptr); \
} else { \
__chk_user_ptr(ptr); \
Expand All @@ -297,7 +312,7 @@ do { \
\
might_fault(); \
if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) { \
if (segment_eq(get_fs(), get_ds())) \
if (eva_kernel_access()) \
__get_kernel_common((x), size, __gu_ptr); \
else \
__get_user_common((x), size, __gu_ptr); \
Expand Down Expand Up @@ -422,7 +437,7 @@ do { \
int __pu_err = 0; \
\
__pu_val = (x); \
if (segment_eq(get_fs(), get_ds())) { \
if (eva_kernel_access()) { \
__put_kernel_common(ptr, size); \
} else { \
__chk_user_ptr(ptr); \
Expand All @@ -439,7 +454,7 @@ do { \
\
might_fault(); \
if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) { \
if (segment_eq(get_fs(), get_ds())) \
if (eva_kernel_access()) \
__put_kernel_common(__pu_addr, size); \
else \
__put_user_common(__pu_addr, size); \
Expand Down Expand Up @@ -833,7 +848,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
__cu_from = (from); \
__cu_len = (n); \
might_fault(); \
if (segment_eq(get_fs(), get_ds())) \
if (eva_kernel_access()) \
__cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from, \
__cu_len); \
else \
Expand All @@ -853,7 +868,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
if (segment_eq(get_fs(), get_ds())) \
if (eva_kernel_access()) \
__cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from, \
__cu_len); \
else \
Expand All @@ -871,7 +886,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
if (segment_eq(get_fs(), get_ds())) \
if (eva_kernel_access()) \
__cu_len = __invoke_copy_from_kernel_inatomic(__cu_to, \
__cu_from,\
__cu_len);\
Expand Down Expand Up @@ -904,7 +919,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
if (segment_eq(get_fs(), get_ds())) { \
if (eva_kernel_access()) { \
__cu_len = __invoke_copy_to_kernel(__cu_to, \
__cu_from, \
__cu_len); \
Expand Down Expand Up @@ -1126,7 +1141,7 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
if (segment_eq(get_fs(), get_ds())) { \
if (eva_kernel_access()) { \
__cu_len = __invoke_copy_from_kernel(__cu_to, \
__cu_from, \
__cu_len); \
Expand All @@ -1150,7 +1165,7 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
if (segment_eq(get_fs(), get_ds())) { \
if (eva_kernel_access()) { \
__cu_len = ___invoke_copy_in_kernel(__cu_to, __cu_from, \
__cu_len); \
} else { \
Expand All @@ -1170,7 +1185,7 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
if (segment_eq(get_fs(), get_ds())) { \
if (eva_kernel_access()) { \
__cu_len = ___invoke_copy_in_kernel(__cu_to,__cu_from, \
__cu_len); \
} else { \
Expand Down Expand Up @@ -1250,7 +1265,7 @@ __strncpy_from_user(char *__to, const char __user *__from, long __len)
{
long res;

if (segment_eq(get_fs(), get_ds())) {
if (eva_kernel_access()) {
__asm__ __volatile__(
"move\t$4, %1\n\t"
"move\t$5, %2\n\t"
Expand Down Expand Up @@ -1299,7 +1314,7 @@ strncpy_from_user(char *__to, const char __user *__from, long __len)
{
long res;

if (segment_eq(get_fs(), get_ds())) {
if (eva_kernel_access()) {
__asm__ __volatile__(
"move\t$4, %1\n\t"
"move\t$5, %2\n\t"
Expand Down Expand Up @@ -1343,7 +1358,7 @@ static inline long strlen_user(const char __user *s)
{
long res;

if (segment_eq(get_fs(), get_ds())) {
if (eva_kernel_access()) {
__asm__ __volatile__(
"move\t$4, %1\n\t"
__MODULE_JAL(__strlen_kernel_asm)
Expand All @@ -1370,7 +1385,7 @@ static inline long __strnlen_user(const char __user *s, long n)
{
long res;

if (segment_eq(get_fs(), get_ds())) {
if (eva_kernel_access()) {
__asm__ __volatile__(
"move\t$4, %1\n\t"
"move\t$5, %2\n\t"
Expand Down Expand Up @@ -1411,7 +1426,7 @@ static inline long strnlen_user(const char __user *s, long n)
long res;

might_fault();
if (segment_eq(get_fs(), get_ds())) {
if (eva_kernel_access()) {
__asm__ __volatile__(
"move\t$4, %1\n\t"
"move\t$5, %2\n\t"
Expand Down

0 comments on commit 1206066

Please sign in to comment.