lkml.org 
[lkml]   [2009]   [Apr]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
Subject[PATCH] cacheflush system call not returning -EINVAL
From
Hi,

cacheflush man page states that cacheflush() will set EINVAL if cache
parameter is not one of ICACHE, DCACHE, or BCACHE.
In order to confirm this behavior, I have executed the below listed
program (cacheflush_check.c) in Toshiba RBTX4937 board (MIPS) with
2.6.29.1 kernel.

=================================================================
/*
* cacheflush_check.c
*
* Description:
* Tests EINVAL error of cacheflush system call
*
* Expected behaviour:
* cacheflush() should return -EINVAL when cache parameter is not one
of ICACHE, DCACHE, or BCACHE.
*
*/
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#if defined __mips__
#include <asm/cachectl.h>

int cacheflush(char *addr, int nbytes, int cache)
{
return syscall(__NR_cacheflush, addr, nbytes, cache);
}
#endif /* __mips__ */

int main()
{
/* cacheflush man page states that cacheflush() is only
applicable to MIPS architecture */
char *addr = NULL;

/* Create some user address range */
addr = malloc(getpagesize());
if (addr == NULL) {
printf("Malloc error\n");
exit(-1);
}
/* Invokes cacheflush() with proper parameters */
cacheflush(addr, getpagesize(), ICACHE);
cacheflush(addr, getpagesize(), DCACHE);
cacheflush(addr, getpagesize(), BCACHE);
/* Tests whether cacheflush() returns -EINVAL */
if (cacheflush(addr, getpagesize(), 0) < 0) {
if (errno == EINVAL) {
printf("cacheflush EINVAL : TEST PASS\n");
exit(0);
} else {
printf("cacheflush EINVAL : TEST FAIL\n");
}
}
printf("cacheflush EINVAL : TEST FAIL\n");
return -1;
}
=======================================================
I have observed that the test failed when executed in target board.

-bash-3.2# ./cacheflush_err_check
cacheflush EINVAL : TEST FAIL

I have checked the 'arch/mips/mm/cache.c' and observed that the
cacheflush() implementation is not setting EINVAL.
So, I have modified this file by including these two lines for EINVAL.
if ( (cache != ICACHE) && (cache != DCACHE) && (cache != BCACHE) )
return -EINVAL;
After this modification, I have straced the cacheflush_check program
with the modified kernel:
strace ./cacheflush_check
....
set_thread_area(0x2aacd3e0) = 0
mprotect(0x2ac1a000, 28672, PROT_READ) = 0
mprotect(0x2aad4000, 4096, PROT_READ) = 0
brk(0) = 0x411000
brk(0x432000) = 0x432000
syscall(0x1033, 0x411050, 0x1000, 0x1, 0x418e90, 0x2aac5280, 0x418e90,
0x2aad4ef0) = 0
syscall(0x1033, 0x411050, 0x1000, 0x2, 0x418e90, 0x2aac5280, 0x418e90,
0x2aad4ef0) = 0
syscall(0x1033, 0x411050, 0x1000, 0x3, 0x418e90, 0x2aac5280, 0x418e90,
0x2aad4ef0) = 0
syscall(0x1033, 0x411050, 0x1000, 0, 0x418e90, 0x2aac5280, 0x418e90,
0x2aad4ef0) = -1 EINVAL (Invalid argument)
fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
old_mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0) = 0x2ac2a000
....
The test passes when executed in the modified kernel.I have tested
this patch and seen no adverse effects.
Cheers,

Signed-off-by: Maxin B. John <maxinbjohn@gmail.com>

--------
diff -uNr linux-2.6.29.1/arch/mips/mm/cache.c
linux-2.6.29.1-a/arch/mips/mm/cache.c
--- linux-2.6.29.1/arch/mips/mm/cache.c 2009-04-03 02:25:27.000000000 +0530
+++ linux-2.6.29.1-a/arch/mips/mm/cache.c 2009-04-09
18:24:50.000000000 +0530
@@ -64,6 +64,10 @@
{
if (bytes == 0)
return 0;
+
+ if ( (cache != ICACHE) && (cache != DCACHE) && (cache != BCACHE) )
+ return -EINVAL;
+
if (!access_ok(VERIFY_WRITE, (void __user *) addr, bytes))
return -EFAULT;

----------

\
 
 \ /
  Last update: 2009-04-09 15:05    [from the cache]
©2003-2011 Jasper Spaans