Monday, April 13, 2015

Armv8 - 32bit app with 64k page and 64bit Kernel

With binutils 2.25 the default alignment for 32bit arm sections changed to have everything 64k aligned.  Armv7 binaries built with this binutils version run successfully on an arm64 system with required chnages from Kernel side.

Page faults will be less with 64k page size.

config COMPAT
bool "Kernel support for 32-bit EL0"
depends on !ARM64_64K_PAGES  - remove this line
select COMPAT_BINFMT_ELF
select HAVE_UID16
select OLD_SIGSUSPEND3

If we remove "depends on !ARM64_64K_PAGES" this , COMPAT feature will be enabled for All page sizes . 

Unfortunately  the 32bit glibc has a bogus mmap() implementation that hard codes 4k page size. Then How to handle 64K page support for 32bit apps?


2 ways to handle 64k page support.

1) stick with the sys_mmap() for 64-bit systems and avoid offset conversion in both glibc and kernel

2) use sys_mmap2() with a 12 shift in glibc and (PAGE_SHIFT - 12) in the kernel wrapper?

As of now we are going with 2nd option .

Patches required to Support 64K page size for 32bit Apps:

http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/329798.html

The arm mmap2 syscall takes the offset in units of 4K, thus with 64K pages the offset needs to be scaled to units of pages.

--- a/arch/arm64/kernel/entry32.S
+++ b/arch/arm64/kernel/entry32.S
@@ -19,9 +19,12 @@
*/
#include <linux/linkage.h>
+#include <linux/const.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
+#include <asm/errno.h>
+#include <asm/page.h>
/*
* System call wrappers for the AArch32 compatibility layer.
@@ -54,6 +57,21 @@ ENTRY(compat_sys_fstatfs64_wrapper)
ENDPROC(compat_sys_fstatfs64_wrapper)
/*
+ * Note: off_4k (w5) is always units of 4K. If we can't do the requested
+ * offset, we return EINVAL.
+ */
+#if PAGE_SHIFT > 12
+ENTRY(compat_sys_mmap2_wrapper)
+ tst w5, #~PAGE_MASK >> 12
+ b.ne 1f
+ lsr w5, w5, #PAGE_SHIFT - 12
+ b sys_mmap_pgoff
+1: mov x0, #-EINVAL
+ ret lr
+ENDPROC(compat_sys_mmap2_wrapper)
+#endif
+
+/*
* Wrappers for AArch32 syscalls that either take 64-bit parameters
* in registers or that take 32-bit parameters which require sign
* extension.


sys_mmap2 is indeed independent of the page size on most architectures assuming that the last argument represents the offset in units of 4096.

sys_mmap is also independent of the page size.

In Option 2 We end up doing a shift by 12 in glibc and another shift by (PAGE_SHIFT - 12) in the kernel wrapper. As we rather than fixating in glibc we are fixing in kernel side.

If glibc supports , we can avoid this patch.

No comments:

Post a Comment