os-android: Add support to android platform
RFC PATCH v2 1/1 os-android: Add support to android platform
This is patch to build qemu for android platfrom. The building uses NDK r10 cross-compilation toolchain with following changes:
- install qemu dependent libraries
- upgrade bionic libc
- add mssing includes, scsi/sg.h, in toolchain
- make a symbolic link x86_64-linux-android-pkg-config that links to host's pkg-config.
Then, configure and build static linked qemu by commands:
$ export SYSROOT="/opt/android-toolchain64/sysroot"
$ PKG_CONFIG_LIBDIR=/opt/android-toolchain64/sysroot/usr/lib/pkgconfig \
./configure \
--cross-prefix=x86_64-linux-android- --enable-kvm \
--enable-trace-backend=nop --disable-fdt --target-list=x86_64-softmmu \
--disable-spice --disable-vhost-net --disable-libiscsi \
--audio-drv-list="" --disable-gtk --disable-gnutls \
--disable-libnfs --disable-glusterfs --disable-libssh2 \
--disable-seccomp --disable-usb-redir --disable-libusb \
--disable-guest-agent --static
$ make -j4For dynamic build, you can skip the "static" option during configure, copy dependent so files into android and add "." into LD_LIBRARY_PATH.
How to prepare your cross-compilation toolcahin
-----------------------------------------------
1. Download NDK r10, install toolchain from NDK and build the following libraries and install in your toolchain sysroot:
libiconv-1.14
gettext-0.19
libffi-3.0.12
glib-2.34.3
libpng-1.2.52
pixman-0.302. Download AOSP and apply this patch I made to support posix lockf()
https://android-review.googlesource.com/#/c/172150/
3. Build bionic C and update your toolchain's libc.a and libc.so.
4. Copy kernel header file, scsi/sg.h into toolchain's sysroot/usr/includes/scsi/
5. Update these header files in your toolchain to prevent compilation warning, includes:
unistd.h for lockf() and related define
sys/uio.h for pread() and pwrite()
signal.h for sigtimedwait()
--- configure | 18 ++++++++++++++++-- default-configs/pci.mak | 2 +- hw/i386/kvm/pci-assign.c | 1 - include/qemu/osdep.h | 7 +++++++ include/sysemu/os-android.h | 12 ++++++++++++ kvm-all.c | 4 ++++ tests/Makefile | 2 ++ util/oslib-posix.c | 12 ++++++++++++ util/qemu-openpty.c | 19 ++++++++++++++----- 9 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 include/sysemu/os-android.h
configure +16 -2
@@ -567,7 +567,6 @@ fi # host *BSD for user mode HOST_VARIANT_DIR="" - case $targetos in CYGWIN*) mingw32="yes"
@@ -693,9 +692,20 @@ Haiku) vhost_net="yes" vhost_scsi="yes" QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES" + case $cross_prefix in + *android*) + android="yes" + ;; + *) + ;; + esac ;; esac +if [ "$android" = "yes" ] ; then + LIBS="-lglib-2.0 -lgthread-2.0 -lz -lpixman-1 -lintl -liconv -lc $LIBS" + libs_qga="-lglib-2.0 -lgthread-2.0 -lz -lpixman-1 -lintl -liconv -lc" +fi if [ "$bsd" = "yes" ] ; then if [ "$darwin" != "yes" ] ; then bsd_user="yes"
@@ -3791,7 +3801,7 @@ elif compile_prog "" "$pthread_lib -lrt" ; then fi if test "$darwin" != "yes" -a "$mingw32" != "yes" -a "$solaris" != yes -a \ - "$aix" != "yes" -a "$haiku" != "yes" ; then + "$aix" != "yes" -a "$haiku" != "yes" -a "$android" != "yes" ; then libs_softmmu="-lutil $libs_softmmu" fi
@@ -4737,6 +4747,10 @@ if test "$linux" = "yes" ; then echo "CONFIG_LINUX=y" >> $config_host_mak fi +if test "$android" = "yes" ; then + echo "CONFIG_ANDROID=y" >> $config_host_mak +fi + if test "$darwin" = "yes" ; then echo "CONFIG_DARWIN=y" >> $config_host_mak fi
default-configs/pci.mak +1 -1
@@ -35,5 +35,5 @@ CONFIG_SDHCI=y CONFIG_EDU=y CONFIG_VGA=y CONFIG_VGA_PCI=y -CONFIG_IVSHMEM=$(CONFIG_KVM) +CONFIG_IVSHMEM=$(call land,$(call lnot,$(CONFIG_ANDROID)),$(CONFIG_KVM)) CONFIG_ROCKER=y
hw/i386/kvm/pci-assign.c +0 -1
@@ -22,7 +22,6 @@*/ #include <stdio.h> #include <unistd.h> -#include <sys/io.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h>
include/qemu/osdep.h +7 -0
@@ -59,6 +59,10 @@#define WEXITSTATUS (x) (x)#endif +#ifdef CONFIG_ANDROID +#include "sysemu/os-android.h" +#endif +#ifdef _WIN32#include "sysemu/os-win32.h" #endif
@@ -284,4 +288,7 @@ void os_mem_prealloc(int fd, char *area, size_t sz);int qemu_read_password (char *buf,int buf_size); +int qemu_getdtablesize (void ); + +#endif
include/sysemu/os-android.h new file +12 -0
@@ -0,0 +1,12 @@ +#ifndef QEMU_OS_ANDROID_H +#define QEMU_OS_ANDROID_H + +/* +* For include the basename prototyping in android. +*/ +#include <libgen.h> + +#define getdtablesize qemu_getdtablesize +#define IOV_MAX 1024 + +#endif
kvm-all.c +4 -0
@@ -45,7 +45,11 @@#endif /* KVM uses PAGE_SIZE in its definition of COALESCED_MMIO_MAX */ +#ifdef PAGE_SIZE +QEMU_BUILD_BUG_ON (PAGE_SIZE !=TARGET_PAGE_SIZE ); +#else #define PAGE_SIZE TARGET_PAGE_SIZE +#endif //#define DEBUG_KVM
tests/Makefile +2 -0
@@ -418,8 +418,10 @@ tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o libqemuutil.a libqemustub. tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(block-obj-y) libqemuutil.a libqemustub.a ifeq ($(CONFIG_POSIX),y) +ifneq ($(CONFIG_ANDROID),y) LIBS += -lutil endif +endif # QTest rules
util/oslib-posix.c +12 -0
@@ -62,6 +62,8 @@ extern int daemon(int, int);#include <libgen.h> #include <setjmp.h> #include <sys/signal.h> +#include <sys/time.h> +#include <sys/resource.h> #ifdef CONFIG_LINUX #include <sys/syscall.h>
@@ -482,3 +484,13 @@ int qemu_read_password(char *buf, int buf_size)printf ("\n" );return ret; } + +int qemu_getdtablesize (void ) +{ +struct rlimit r; + +if (getrlimit (RLIMIT_NOFILE , &r) <0 ) { +return sysconf (_SC_OPEN_MAX); + } +return r.rlim_cur; +}
util/qemu-openpty.c +14 -5
@@ -51,11 +51,16 @@# include <termios.h> #endif -#ifdef __sun__ +#if defined(__sun__) || defined(CONFIG_ANDROID ) +/* Once Solaris has openpty(), this is going to be removed. */ static int openpty (int *amaster,int *aslave,char *name,struct termios *termp,struct winsize *winp) { +#if defined(CONFIG_ANDROID ) +char pty_buf[PATH_MAX ]; +#define ptsname (fd) pty_buf +#endif const char *slave;int mfd =-1 , sfd =-1 ;
@@ -67,17 +72,20 @@ static int openpty(int *amaster, int *aslave, char *name,if (grantpt (mfd) ==-1 ||unlockpt (mfd) ==-1 ) goto err; - +#if defined(CONFIG_ANDROID ) +ptsname_r (mfd, pty_buf,PATH_MAX ); +#endif if ((slave =ptsname (mfd)) ==NULL ) goto err;if ((sfd =open (slave,O_RDONLY |O_NOCTTY )) ==-1 ) goto err; +#ifndef CONFIG_ANDROID if (ioctl (sfd,I_PUSH ,"ptem" ) ==-1 || (termp !=NULL &&tcgetattr (sfd, termp) <0 )) goto err; - +#endif if (amaster) *amaster = mfd;if (aslave)
@@ -93,7 +101,8 @@ err:close (mfd);return -1 ; } - +#endif +#ifdef __sun__static void cfmakeraw (struct termios *termios_p) { termios_p->c_iflag &=
@@ -112,7 +121,7 @@ int qemu_openpty_raw(int *aslave, char *pty_name) {int amaster;struct termios tty; -#if defined(__OpenBSD__) || defined(__DragonFly__) +#if defined(__OpenBSD__) || defined(__DragonFly__) || defined(CONFIG_ANDROID )char pty_buf[PATH_MAX ];#define q_ptsname (x) pty_buf#else
Signature · 1 line
1.9.1
Quoted 186 lines · Houcheng Lin
This is patch to build qemu for android platfrom. The building uses NDK r10 cross-compilation toolchain with following changes:
- install qemu dependent libraries
- upgrade bionic libc
- add mssing includes,scsi/sg.h, in toolchain
- make a symbolic link x86_64-linux-android-pkg-config that links to host's pkg-config.Then, configure and build static linked qemu by commands:
$ export SYSROOT="/opt/android-toolchain64/sysroot" $ PKG_CONFIG_LIBDIR=/opt/android-toolchain64/sysroot/usr/lib/pkgconfig \ ./configure \ --cross-prefix=x86_64-linux-android- --enable-kvm \ --enable-trace-backend=nop --disable-fdt --target-list=x86_64-softmmu \ --disable-spice --disable-vhost-net --disable-libiscsi \ --audio-drv-list="" --disable-gtk --disable-gnutls \ --disable-libnfs --disable-glusterfs --disable-libssh2 \ --disable-seccomp --disable-usb-redir --disable-libusb \ --disable-guest-agent --static $ make -j4For dynamic build, you can skip the "static" option during configure, copy dependent so files into android and add "." into
LD_LIBRARY_PATH.How to prepare your cross-compilation toolcahin
-----------------------------------------------1. Download NDK r10, install toolchain from NDK and build the following libraries and install in your toolchain sysroot:
libiconv-1.14 gettext-0.19 libffi-3.0.12 glib-2.34.3 libpng-1.2.52 pixman-0.302. Download AOSP and apply this patch I made to support posix
lockf()https://android-review.googlesource.com/#/c/172150/3. Build bionic C and update your toolchain's libc.a and libc.so.
4. Copy kernel header file,
scsi/sg.hinto toolchain's sysroot/usr/includes/scsi/5. Update these header files in your toolchain to prevent compilation warning, includes:
unistd.hforlockf()and related define
sys/uio.hforpread()andpwrite()
signal.hforsigtimedwait()Signed-off-by Houcheng Lin <[email protected]>--- configure | 18 ++++++++++++++++-- default-configs/pci.mak | 2 +- hw/i386/kvm/pci-assign.c | 1 - include/qemu/osdep.h | 7 +++++++ include/sysemu/os-android.h | 12 ++++++++++++ kvm-all.c | 4 ++++ tests/Makefile | 2 ++ util/oslib-posix.c | 12 ++++++++++++ util/qemu-openpty.c | 19 ++++++++++++++----- 9 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 include/sysemu/os-android.hconfigure +16
-2@@ -567,7 +567,6 @@ fi # host *BSD for user mode HOST_VARIANT_DIR="" - case $targetos in CYGWIN*) mingw32="yes"@@ -693,9 +692,20 @@ Haiku) vhost_net="yes" vhost_scsi="yes" QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES" + case $cross_prefix in + *android*) + android="yes" + ;; + *) + ;; + esac ;; esac +if [ "$android" = "yes" ] ; then + LIBS="-lglib-2.0 -lgthread-2.0 -lz -lpixman-1 -lintl -liconv -lc $LIBS" + libs_qga="-lglib-2.0 -lgthread-2.0 -lz -lpixman-1 -lintl -liconv -lc" +fi if [ "$bsd" = "yes" ] ; then if [ "$darwin" != "yes" ] ; then bsd_user="yes"@@ -3791,7 +3801,7 @@ elif compile_prog "" "$pthread_lib -lrt" ; then fi if test "$darwin" != "yes" -a "$mingw32" != "yes" -a "$solaris" != yes -a \ - "$aix" != "yes" -a "$haiku" != "yes" ; then + "$aix" != "yes" -a "$haiku" != "yes" -a "$android" != "yes" ; then libs_softmmu="-lutil $libs_softmmu" fi@@ -4737,6 +4747,10 @@ if test "$linux" = "yes" ; then echo "CONFIG_LINUX=y" >> $config_host_mak fi +if test "$android" = "yes" ; then + echo "CONFIG_ANDROID=y" >> $config_host_mak +fi + if test "$darwin" = "yes" ; then echo "CONFIG_DARWIN=y" >> $config_host_mak fidefault-configs/pci.mak +1
-1@@ -35,5 +35,5 @@ CONFIG_SDHCI=y CONFIG_EDU=y CONFIG_VGA=y CONFIG_VGA_PCI=y -CONFIG_IVSHMEM=$(CONFIG_KVM) +CONFIG_IVSHMEM=$(call land,$(call lnot,$(CONFIG_ANDROID)),$(CONFIG_KVM)) CONFIG_ROCKER=yhw/i386/kvm/pci-assign.c +0
-1@@ -22,7 +22,6 @@*/ #include <stdio.h> #include <unistd.h> -#include <sys/io.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> include/qemu/osdep.h +7
-0@@ -59,6 +59,10 @@#define WEXITSTATUS (x) (x)#endif +#ifdef CONFIG_ANDROID +#include "sysemu/os-android.h" +#endif +#ifdef _WIN32#include "sysemu/os-win32.h" #endif @@ -284,4 +288,7 @@ void os_mem_prealloc(int fd, char *area, size_t sz);int qemu_read_password (char *buf,int buf_size); +int qemu_getdtablesize (void ); + +#endif include/sysemu/os-android.h new file +12
-0@@ -0,0 +1,12 @@ +#ifndef QEMU_OS_ANDROID_H +#define QEMU_OS_ANDROID_H + +/* +* For include the basename prototyping in android. +*/ +#include <libgen.h> + +#define getdtablesize qemu_getdtablesize +#define IOV_MAX 1024 + +#endif kvm-all.c +0
-0
kvm-all.c line 52
Quoted 8 lines
kvm-all.c +4
-0@@ -45,7 +45,11 @@#endif /* KVM uses PAGE_SIZE in its definition of COALESCED_MMIO_MAX */ +#ifdef PAGE_SIZE +QEMU_BUILD_BUG_ON (PAGE_SIZE !=TARGET_PAGE_SIZE ); +#else #define PAGE_SIZE TARGET_PAGE_SIZE +#endif
Is this an Android limitation or a fix for KVM in general? If it is the later it should be split into a separate patch.
Quoted 54 lines
kvm-all.c +0
-0//#define DEBUG_KVM tests/Makefile +2
-0@@ -418,8 +418,10 @@ tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o libqemuutil.a libqemustub. tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(block-obj-y) libqemuutil.a libqemustub.a ifeq ($(CONFIG_POSIX),y) +ifneq ($(CONFIG_ANDROID),y) LIBS += -lutil endif +endif # QTest rulesutil/oslib-posix.c +12
-0@@ -62,6 +62,8 @@ extern int daemon(int, int);#include <libgen.h> #include <setjmp.h> #include <sys/signal.h> +#include <sys/time.h> +#include <sys/resource.h> #ifdef CONFIG_LINUX #include <sys/syscall.h> @@ -482,3 +484,13 @@ int qemu_read_password(char *buf, int buf_size)printf ("\n" );return ret; } + +int qemu_getdtablesize (void ) +{ +struct rlimit r; + +if (getrlimit (RLIMIT_NOFILE , &r) <0 ) { +return sysconf (_SC_OPEN_MAX); + } +return r.rlim_cur; +}util/qemu-openpty.c +0
-1@@ -51,11 +51,16 @@# include <termios.h> #endif -#ifdef __sun__
util/qemu-openpty.c line 63
Quoted 10 lines
util/qemu-openpty.c +6
-0+#if defined(__sun__) || defined(CONFIG_ANDROID ) +/* Once Solaris has openpty(), this is going to be removed. */ static int openpty (int *amaster,int *aslave,char *name,struct termios *termp,struct winsize *winp) { +#if defined(CONFIG_ANDROID ) +char pty_buf[PATH_MAX ]; +#define ptsname (fd) pty_buf +#endif
Indentation not consistent with the rest of the function.
util/qemu-openpty.c static int openpty(int *amaster, int *aslave, char *name, · line 77
Quoted 11 lines
util/qemu-openpty.c +3
-1const char *slave;int mfd =-1 , sfd =-1 ;@@ -67,17 +72,20 @@ static int openpty(int *amaster, int *aslave, char *name,if (grantpt (mfd) ==-1 ||unlockpt (mfd) ==-1 ) goto err; - +#if defined(CONFIG_ANDROID ) +ptsname_r (mfd, pty_buf,PATH_MAX ); +#endif
Should we be checking for errors here?
Quoted 34 lines
util/qemu-openpty.c +5
-3if ((slave =ptsname (mfd)) ==NULL ) goto err;if ((sfd =open (slave,O_RDONLY |O_NOCTTY )) ==-1 ) goto err; +#ifndef CONFIG_ANDROID if (ioctl (sfd,I_PUSH ,"ptem" ) ==-1 || (termp !=NULL &&tcgetattr (sfd, termp) <0 )) goto err; - +#endif if (amaster) *amaster = mfd;if (aslave)@@ -93,7 +101,8 @@ err:close (mfd);return -1 ; } - +#endif +#ifdef __sun__static void cfmakeraw (struct termios *termios_p) { termios_p->c_iflag &=@@ -112,7 +121,7 @@ int qemu_openpty_raw(int *aslave, char *pty_name) {int amaster;struct termios tty; -#if defined(__OpenBSD__) || defined(__DragonFly__) +#if defined(__OpenBSD__) || defined(__DragonFly__) || defined(CONFIG_ANDROID )char pty_buf[PATH_MAX ];#define q_ptsname (x) pty_buf#else
Signature · 1 line
Alex Bennée