[<prev] [next>] [day] [month] [year] [list]
Message-ID: <9debc4410904090600k3250cc9y5c713c1b0ef6d16b@mail.gmail.com>
Date: Thu, 9 Apr 2009 18:30:53 +0530
From: Maxin John <maxin.john@...il.com>
To: linux-kernel@...r.kernel.org
Cc: kernel-janitors@...r.kernel.org, ralf@...ux-mips.org
Subject: [PATCH] cacheflush system call not returning -EINVAL
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@...il.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;
----------
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists