* mmap is broken for MIPS64 n32 and o32 abis
@ 2008-09-19 6:31 Dinar Temirbulatov
2008-09-19 10:14 ` Sergei Shtylyov
2008-09-19 12:33 ` Maciej W. Rozycki
0 siblings, 2 replies; 8+ messages in thread
From: Dinar Temirbulatov @ 2008-09-19 6:31 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 570 bytes --]
Hi,
I noticed that mmap is not working properly under n32, o32 abis in
MIPS64, for example if we want to map 0xb6000000 address to the
userland under those abis we call mmap and because the last argument
in old_mmap is off_t and this type is 64-bits wide for MIPS64, we end
up having for example 0xffffffffb6000000 address value. I am sure that
this is not a glibc issue. Following patch adds 32-bit version of mmap
and also it adds mmap64 support for n32 abi since mmap64 was
implemented correctly for n32 too.
thanks, Dinar.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: mmap.patch --]
[-- Type: text/x-patch; name=mmap.patch, Size: 2682 bytes --]
diff -ruNp linux-2.6.27-rc6/arch/mips/kernel/scall64-n32.S linux-2.6.27-rc6-fix/arch/mips/kernel/scall64-n32.S
--- linux-2.6.27-rc6/arch/mips/kernel/scall64-n32.S 2008-09-19 09:34:42.000000000 +0400
+++ linux-2.6.27-rc6-fix/arch/mips/kernel/scall64-n32.S 2008-09-19 09:47:13.000000000 +0400
@@ -129,7 +129,7 @@ EXPORT(sysn32_call_table)
PTR sys_newlstat
PTR sys_poll
PTR sys_lseek
- PTR old_mmap
+ PTR sys32_mmap
PTR sys_mprotect /* 6010 */
PTR sys_munmap
PTR sys_brk
@@ -413,4 +413,5 @@ EXPORT(sysn32_call_table)
PTR sys_dup3 /* 5290 */
PTR sys_pipe2
PTR sys_inotify_init1
+ PTR sys32_mmap2
.size sysn32_call_table,.-sysn32_call_table
diff -ruNp linux-2.6.27-rc6/arch/mips/kernel/scall64-o32.S linux-2.6.27-rc6-fix/arch/mips/kernel/scall64-o32.S
--- linux-2.6.27-rc6/arch/mips/kernel/scall64-o32.S 2008-09-19 09:34:42.000000000 +0400
+++ linux-2.6.27-rc6-fix/arch/mips/kernel/scall64-o32.S 2008-09-19 09:47:22.000000000 +0400
@@ -295,7 +295,7 @@ sys_call_table:
PTR sys_swapon
PTR sys_reboot
PTR compat_sys_old_readdir
- PTR old_mmap /* 4090 */
+ PTR sys32_mmap /* 4090 */
PTR sys_munmap
PTR sys_truncate
PTR sys_ftruncate
diff -ruNp linux-2.6.27-rc6/arch/mips/kernel/syscall.c linux-2.6.27-rc6-fix/arch/mips/kernel/syscall.c
--- linux-2.6.27-rc6/arch/mips/kernel/syscall.c 2008-09-19 09:34:42.000000000 +0400
+++ linux-2.6.27-rc6-fix/arch/mips/kernel/syscall.c 2008-09-19 09:46:52.000000000 +0400
@@ -170,6 +170,22 @@ out:
}
asmlinkage unsigned long
+sys32_mmap(unsigned long addr, unsigned long len, int prot,
+ int flags, int fd, unsigned int offset offset)
+{
+ unsigned long result;
+
+ result = -EINVAL;
+ if (offset & ~PAGE_MASK)
+ goto out;
+
+ result = do_mmap2(addr, len, prot, flags, fd, (unsigned long) offset >> PAGE_SHIFT);
+
+out:
+ return result;
+}
+
+asmlinkage unsigned long
sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
unsigned long flags, unsigned long fd, unsigned long pgoff)
{
diff -ruNp linux-2.6.27-rc6/include/asm-mips/unistd.h linux-2.6.27-rc6-fix/include/asm-mips/unistd.h
--- linux-2.6.27-rc6/include/asm-mips/unistd.h 2008-09-19 09:34:43.000000000 +0400
+++ linux-2.6.27-rc6-fix/include/asm-mips/unistd.h 2008-09-19 09:50:26.000000000 +0400
@@ -966,11 +966,12 @@
#define __NR_dup3 (__NR_Linux + 290)
#define __NR_pipe2 (__NR_Linux + 291)
#define __NR_inotify_init1 (__NR_Linux + 292)
+#define __NR_mmap2 (__NR_Linux + 293)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 292
+#define __NR_Linux_syscalls 293
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: mmap is broken for MIPS64 n32 and o32 abis
2008-09-19 6:31 mmap is broken for MIPS64 n32 and o32 abis Dinar Temirbulatov
@ 2008-09-19 10:14 ` Sergei Shtylyov
2008-09-19 12:33 ` Maciej W. Rozycki
1 sibling, 0 replies; 8+ messages in thread
From: Sergei Shtylyov @ 2008-09-19 10:14 UTC (permalink / raw)
To: Dinar Temirbulatov; +Cc: linux-mips
Hello.
Dinar Temirbulatov wrote:
> I noticed that mmap is not working properly under n32, o32 abis in
> MIPS64, for example if we want to map 0xb6000000 address to the
> userland under those abis we call mmap and because the last argument
> in old_mmap is off_t and this type is 64-bits wide for MIPS64, we end
> up having for example 0xffffffffb6000000 address value. I am sure that
> this is not a glibc issue. Following patch adds 32-bit version of mmap
> and also it adds mmap64 support for n32 abi since mmap64 was
> implemented correctly for n32 too.
> thanks, Dinar.
>
Your patch (BTW, how come it didn't get quoted? -- ah, it's
text/x-patch) is using both tabs and spaces for indentation. Please use
tabs only.
And either attach patches as text/plain or include them inline.
WBR, Sergei
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: mmap is broken for MIPS64 n32 and o32 abis
2008-09-19 6:31 mmap is broken for MIPS64 n32 and o32 abis Dinar Temirbulatov
2008-09-19 10:14 ` Sergei Shtylyov
@ 2008-09-19 12:33 ` Maciej W. Rozycki
2008-09-19 16:53 ` Dinar Temirbulatov
1 sibling, 1 reply; 8+ messages in thread
From: Maciej W. Rozycki @ 2008-09-19 12:33 UTC (permalink / raw)
To: Dinar Temirbulatov; +Cc: linux-mips
On Fri, 19 Sep 2008, Dinar Temirbulatov wrote:
> I noticed that mmap is not working properly under n32, o32 abis in
> MIPS64, for example if we want to map 0xb6000000 address to the
> userland under those abis we call mmap and because the last argument
> in old_mmap is off_t and this type is 64-bits wide for MIPS64, we end
> up having for example 0xffffffffb6000000 address value. I am sure that
> this is not a glibc issue. Following patch adds 32-bit version of mmap
> and also it adds mmap64 support for n32 abi since mmap64 was
> implemented correctly for n32 too.
Well, neither with the o32 nor with the n32 ABI are 0xb6000000 or
0xffffffffb6000000 (which is the n32's equivalent of the former) valid
user addresses, so your concern is?
Maciej
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: mmap is broken for MIPS64 n32 and o32 abis
2008-09-19 12:33 ` Maciej W. Rozycki
@ 2008-09-19 16:53 ` Dinar Temirbulatov
2008-09-19 17:25 ` Maciej W. Rozycki
0 siblings, 1 reply; 8+ messages in thread
From: Dinar Temirbulatov @ 2008-09-19 16:53 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: linux-mips
Hi,
The first address 0xb6000000 is a physical memory 32-bit address that
we are trying to map under n32 or o32 and it is valid.
mmh = open("/dev/mem", O_RDWR | O_SYNC);
if (mmh < 0) {
.....
}
mmptr = (unsigned short *)mmap((void *)0, 0x1000,
PROT_READ | PROT_WRITE, MAP_SHARED,
mmh, 0xb6000000);
...
and the second one 0xffffffffb6000000 address is that old_mmap have
got on the kernel side when we do mmap under those abis, calling
do_mmap2 after that with 0xffffffffb6000000 last parameter. This
example above works correctly only under n64 abi.
thanks, Dinar.
On Fri, Sep 19, 2008 at 4:33 PM, Maciej W. Rozycki <macro@linux-mips.org> wrote:
> On Fri, 19 Sep 2008, Dinar Temirbulatov wrote:
>
>> I noticed that mmap is not working properly under n32, o32 abis in
>> MIPS64, for example if we want to map 0xb6000000 address to the
>> userland under those abis we call mmap and because the last argument
>> in old_mmap is off_t and this type is 64-bits wide for MIPS64, we end
>> up having for example 0xffffffffb6000000 address value. I am sure that
>> this is not a glibc issue. Following patch adds 32-bit version of mmap
>> and also it adds mmap64 support for n32 abi since mmap64 was
>> implemented correctly for n32 too.
>
> Well, neither with the o32 nor with the n32 ABI are 0xb6000000 or
> 0xffffffffb6000000 (which is the n32's equivalent of the former) valid
> user addresses, so your concern is?
>
> Maciej
>
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: mmap is broken for MIPS64 n32 and o32 abis
2008-09-19 16:53 ` Dinar Temirbulatov
@ 2008-09-19 17:25 ` Maciej W. Rozycki
2008-09-21 10:55 ` Dinar Temirbulatov
0 siblings, 1 reply; 8+ messages in thread
From: Maciej W. Rozycki @ 2008-09-19 17:25 UTC (permalink / raw)
To: Dinar Temirbulatov; +Cc: linux-mips
On Fri, 19 Sep 2008, Dinar Temirbulatov wrote:
> mmptr = (unsigned short *)mmap((void *)0, 0x1000,
> PROT_READ | PROT_WRITE, MAP_SHARED,
> mmh, 0xb6000000);
Ah, so it is the file offset you are concerned about. Fair enough then.
Obviously the non-LFS 32-bit variation has to sign-extend the offset as
this is how the off_t type has been defined in this case, though it is
interesting to note that the kernel treats this argument as unsigned while
the C library API defines it as signed and there is no range checking in
between. Hmm...
Maciej
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: mmap is broken for MIPS64 n32 and o32 abis
2008-09-19 17:25 ` Maciej W. Rozycki
@ 2008-09-21 10:55 ` Dinar Temirbulatov
2008-09-23 12:32 ` Maciej W. Rozycki
0 siblings, 1 reply; 8+ messages in thread
From: Dinar Temirbulatov @ 2008-09-21 10:55 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: linux-mips
hi, Maciej
I don't think it has anything to do type definition of signed or
unsigned. I think following things happened here we called mmap() from
n32 and as it is defined is the glibc for this abi the sixth parameter
should be 32-bit wide integer and we transefed this 32-bit
value(0xb6000000) in the a5(r9) register according to the mips abi,
but we loaded this value with "lui a5,0xb600" instruction and that
resulted with 0xffffffffb6000000 in the 64-bit version of a5
register(for 32-bit it is legitimate 0xb6000000). after that on the
kernel side we have this function old_mmap() and sixth argument there
is 64-bit wide integer (off_t type) and it does not that we called
this function from 32-bit environment and that is why there is
0xffffffffb6000000 value in the end, so 0xffffffff is trash. I think
that we need to have a separate mmap system call handler for 32-bit
abis, also we need to add mmap2 handler for n32 as we have it for o32.
thanks, Dinar.
On Fri, Sep 19, 2008 at 9:25 PM, Maciej W. Rozycki <macro@linux-mips.org> wrote:
> On Fri, 19 Sep 2008, Dinar Temirbulatov wrote:
>
>> mmptr = (unsigned short *)mmap((void *)0, 0x1000,
>> PROT_READ | PROT_WRITE, MAP_SHARED,
>> mmh, 0xb6000000);
>
> Ah, so it is the file offset you are concerned about. Fair enough then.
> Obviously the non-LFS 32-bit variation has to sign-extend the offset as
> this is how the off_t type has been defined in this case, though it is
> interesting to note that the kernel treats this argument as unsigned while
> the C library API defines it as signed and there is no range checking in
> between. Hmm...
>
> Maciej
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: mmap is broken for MIPS64 n32 and o32 abis
2008-09-21 10:55 ` Dinar Temirbulatov
@ 2008-09-23 12:32 ` Maciej W. Rozycki
2008-09-25 12:34 ` Dinar Temirbulatov
0 siblings, 1 reply; 8+ messages in thread
From: Maciej W. Rozycki @ 2008-09-23 12:32 UTC (permalink / raw)
To: Dinar Temirbulatov; +Cc: linux-mips
Hi Dinar,
> I don't think it has anything to do type definition of signed or
> unsigned. I think following things happened here we called mmap() from
> n32 and as it is defined is the glibc for this abi the sixth parameter
> should be 32-bit wide integer and we transefed this 32-bit
> value(0xb6000000) in the a5(r9) register according to the mips abi,
> but we loaded this value with "lui a5,0xb600" instruction and that
> resulted with 0xffffffffb6000000 in the 64-bit version of a5
> register(for 32-bit it is legitimate 0xb6000000). after that on the
Which is correct, as this is how 32-bit integers are represented by
64-bit MIPS platforms.
> kernel side we have this function old_mmap() and sixth argument there
> is 64-bit wide integer (off_t type) and it does not that we called
> this function from 32-bit environment and that is why there is
> 0xffffffffb6000000 value in the end, so 0xffffffff is trash. I think
> that we need to have a separate mmap system call handler for 32-bit
> abis, also we need to add mmap2 handler for n32 as we have it for o32.
The problem is you cannot represent the file offset of 3053453312 or
0x00000000b6000000 using the 32-bit interface. What you can represent is
-1241513984 or 0xffffffffb6000000 and that is a valid offset for calls
like lseek(), but not necessarily mmap() (though arguably we have a
bug/feature in Linux where negative offsets are not explicitly checked for
in mmap()). To represent 3053453312 or 0x00000000b6000000 correctly you
need to use the 64-bit interface LFS calls provide. In this case that
would be mmap64() or use _FILE_OFFSET_BITS as appropriate.
Maciej
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: mmap is broken for MIPS64 n32 and o32 abis
2008-09-23 12:32 ` Maciej W. Rozycki
@ 2008-09-25 12:34 ` Dinar Temirbulatov
0 siblings, 0 replies; 8+ messages in thread
From: Dinar Temirbulatov @ 2008-09-25 12:34 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: linux-mips
On Tue, Sep 23, 2008 at 4:32 PM, Maciej W. Rozycki <macro@linux-mips.org> wrote:
> The problem is you cannot represent the file offset of 3053453312 or
> 0x00000000b6000000 using the 32-bit interface. What you can represent is
> -1241513984 or 0xffffffffb6000000 and that is a valid offset for calls
> like lseek(), but not necessarily mmap() (though arguably we have a
> bug/feature in Linux where negative offsets are not explicitly checked for
> in mmap()). To represent 3053453312 or 0x00000000b6000000 correctly you
> need to use the 64-bit interface LFS calls provide. In this case that
> would be mmap64() or use _FILE_OFFSET_BITS as appropriate.
yes, this is correct, thanks Maciej.
but there is another problem on n32 abi, kernel does not provide
mmap64() system call for n32 and that results on following problem of
the glibc side: The generic implementation of __mmap64() returns an
error if the value passed in for the "offset" parameter is greater
than what can fit in a __off_t, which for n32 is 2^32. This prevents
mmap64() from being used to map file offsets greater than 2^32 bytes
for n32.
I think this change is required:
diff -ruNp linux-2.6.27-rc6/arch/mips/kernel/scall64-n32.S
linux-2.6.27-rc6-fix/arch/mips/kernel/scall64-n32.S
--- linux-2.6.27-rc6/arch/mips/kernel/scall64-n32.S 2008-09-19
09:34:42.000000000 +0400
+++ linux-2.6.27-rc6-fix/arch/mips/kernel/scall64-n32.S 2008-09-25
16:21:52.000000000 +0400
@@ -413,4 +413,5 @@ EXPORT(sysn32_call_table)
PTR sys_dup3 /* 5290 */
PTR sys_pipe2
PTR sys_inotify_init1
+ PTR sys32_mmap2
.size sysn32_call_table,.-sysn32_call_table
diff -ruNp linux-2.6.27-rc6/include/asm-mips/unistd.h
linux-2.6.27-rc6-fix/include/asm-mips/unistd.h
--- linux-2.6.27-rc6/include/asm-mips/unistd.h 2008-09-19
09:34:43.000000000 +0400
+++ linux-2.6.27-rc6-fix/include/asm-mips/unistd.h 2008-09-19
09:50:26.000000000 +0400
@@ -966,11 +966,12 @@
#define __NR_dup3 (__NR_Linux + 290)
#define __NR_pipe2 (__NR_Linux + 291)
#define __NR_inotify_init1 (__NR_Linux + 292)
+#define __NR_mmap2 (__NR_Linux + 293)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 292
+#define __NR_Linux_syscalls 293
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
thanks, Dinar.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2008-09-25 12:35 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-19 6:31 mmap is broken for MIPS64 n32 and o32 abis Dinar Temirbulatov
2008-09-19 10:14 ` Sergei Shtylyov
2008-09-19 12:33 ` Maciej W. Rozycki
2008-09-19 16:53 ` Dinar Temirbulatov
2008-09-19 17:25 ` Maciej W. Rozycki
2008-09-21 10:55 ` Dinar Temirbulatov
2008-09-23 12:32 ` Maciej W. Rozycki
2008-09-25 12:34 ` Dinar Temirbulatov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox