Improvements for Android:

* All Linux targets: add minimal ioctl support for the ION_IOC family

* Android targets: change proprietary-ioctl support for GPUs from
  being a build-time #define kludge to being controlled by --kernel-variant,
  as it should be.  Update documentation accordingly.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14440 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/NEWS b/NEWS
index 1cadd24..8cf9413 100644
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,9 @@
 
 * Both 32- and 64-bit executables are supported on MacOSX 10.8 and 10.9.
 
+* Configuration for and running on Android targets has changed.
+  See README.android in the source tree for details.
+
 * ================== DEPRECATED FEATURES =================
 
 * --db-attach is now deprecated and will be removed in the next
diff --git a/README.android b/README.android
index cebe2cd..891dcb3 100644
--- a/README.android
+++ b/README.android
@@ -1,9 +1,15 @@
 
-How to cross-compile for Android.  These notes were last updated on 
-17 Feb 2012, for Valgrind SVN revision 12390/2257.
+How to cross-compile and run on Android.  Please read to the end,
+since there are important details further down regarding crash
+avoidance and GPU support.
 
-This is known to work at least for :
-ARM:
+These notes were last updated on 3 Sept 2014, for Valgrind SVN
+revision 14439/2941.
+
+These instructions are known to work, or have worked at some time in
+the past, for:
+
+arm:
   Android 4.0.3 running on a (rooted, AOSP build) Nexus S.
   Android 4.0.3 running on Motorola Xoom.
   Android 4.0.3 running on android arm emulator.
@@ -34,7 +40,7 @@
 
 You can get android-ndk-r6 from
 http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2
-Install it somewhere.  Doesn't matter where.  Then do this:
+Install it somewhere.  Doesn't matter where.  Then:
 
 
 # Modify this (obviously).  Note, this "export" command is only done
@@ -44,25 +50,12 @@
 export NDKROOT=/path/to/android-ndk-r6
 
 
-# Modify this too.  Tell the build system which Android hardware you
-# are building for.  It needs to know this so it can compile in
-# support for the right Android-hw-specific ioctls.  (sigh.)  As with
-# NDKROOT above, this is merely to avoid repeated typing; none of the
-# commands read it.
-#
-# Currently the supported values are:  nexus_s pandaboard
-# So choose one of the below:
-#
-export HWKIND=nexus_s         # Samsung Nexus S; also Xoom (for now)
-export HWKIND=generic         # A generic Android device. eg, Pandaboard
-export HWKIND=emulator        # Android emulator
-
 # Then cd to the root of your Valgrind source tree.
 #
 cd /path/to/valgrind/source/tree
 
 
-# After this point, you don't need to modify anything; just copy and
+# After this point, you don't need to modify anything.  Just copy and
 # paste the commands below.
 
 
@@ -83,6 +76,7 @@
 export LD=$NDKROOT/toolchains/mipsel-linux-android-4.8/prebuilt/linux-x86_64/bin/mipsel-linux-android-ld
 export CC=$NDKROOT/toolchains/mipsel-linux-android-4.8/prebuilt/linux-x86_64/bin/mipsel-linux-android-gcc
 
+
 # Do configuration stuff.  Don't mess with the --prefix in the
 # configure command below, even if you think it's wrong.
 # You may need to set the --with-tmpdir path to something
@@ -94,7 +88,7 @@
 ./autogen.sh
 
 # for ARM
-CPPFLAGS="--sysroot=$NDKROOT/platforms/android-3/arch-arm -DANDROID_HARDWARE_$HWKIND" \
+CPPFLAGS="--sysroot=$NDKROOT/platforms/android-3/arch-arm" \
    CFLAGS="--sysroot=$NDKROOT/platforms/android-3/arch-arm" \
    ./configure --prefix=/data/local/Inst \
    --host=armv7-unknown-linux --target=armv7-unknown-linux \
@@ -103,19 +97,20 @@
 # It is not clear what this platform nr really is.
 
 # for x86
-CPPFLAGS="--sysroot=$NDKROOT/platforms/android-9/arch-x86 -DANDROID_HARDWARE_$HWKIND" \
+CPPFLAGS="--sysroot=$NDKROOT/platforms/android-9/arch-x86" \
    CFLAGS="--sysroot=$NDKROOT/platforms/android-9/arch-x86 -fno-pic" \
    ./configure --prefix=/data/local/Inst \
    --host=i686-android-linux --target=i686-android-linux \
    --with-tmpdir=/sdcard
 
 # for MIPS32
-CPPFLAGS="--sysroot=$NDKROOT/platforms/android-18/arch-mips -DANDROID_HARDWARE_$HWKIND" \
+CPPFLAGS="--sysroot=$NDKROOT/platforms/android-18/arch-mips" \
    CFLAGS="--sysroot=$NDKROOT/platforms/android-18/arch-mips" \
    ./configure --prefix=/data/local/Inst \
    --host=mipsel-linux-android --target=mipsel-linux-android \
    --with-tmpdir=/sdcard
 
+
 # At the end of the configure run, a few lines of details
 # are printed.  Make sure that you see these two lines:
 #
@@ -148,8 +143,26 @@
 #
 adb push Inst /
 
-# To run (on the device)
-/data/local/Inst/bin/valgrind [the usual args etc]
+
+# To run (on the device).  There are two things you need to consider:
+#
+# (1) if you are running on the Android emulator, Valgrind may crash
+#     at startup.  This is because the emulator (for ARM) may not be
+#     simulating a hardware TLS register.  To get around this, run
+#     Valgrind with:
+#       --kernel-variant=android-emulator-no-hw-tls
+# 
+# (2) if you are running a real device, you need to tell Valgrind
+#     what GPU it has, so Valgrind knows how to handle custom GPU
+#     ioctls.  You can choose one of the following:
+#       --kernel-variant=android-gpu-sgx5xx     # PowerVR SGX 5XX series
+#       --kernel-variant=android-gpu-adreno3xx  # Qualcomm Adreno 3XX series
+#     If you don't choose one, the program will still run, but Memcheck
+#     may report false errors after the program performs GPU-specific ioctls.
+#
+# Anyway: to run on the device:
+#
+/data/local/Inst/bin/valgrind [kernel variant args] [the usual args etc]
 
 
 # Once you're up and running, a handy modify-V-rebuild-reinstall
diff --git a/README.android_emulator b/README.android_emulator
index 7548959..f2ed598 100644
--- a/README.android_emulator
+++ b/README.android_emulator
@@ -61,6 +61,14 @@
 adb push Inst /
 
 
+# IMPORTANT: when running Valgrind, you may need give it the flag
+#
+#    --kernel-variant=android-emulator-no-hw-tls
+#
+# since otherwise it may crash at startup.
+# See README.android for details.
+
+
 # if you need to debug:
 # You have on the android side a gdbserver
 # on the device side:
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index a15d55f..7aa8746 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -179,9 +179,11 @@
 "         where hint is one of lax-ioctls fuse-compatible enable-outer\n"
 "           no-inner-prefix no-nptl-pthread-stackcache none\n"
 "    --fair-sched=no|yes|try   schedule threads fairly on multicore systems [no]\n"
-"    --kernel-variant=variant1,variant2,...  handle non-standard kernel"
-                                                               " variants [none]\n"
-"         where variant is one of bproc none\n"
+"    --kernel-variant=variant1,variant2,...\n"
+"         handle non-standard kernel variants [none]\n"
+"         where variant is one of:\n"
+"           bproc android-emulator-no-hw-tls\n"
+"           android-gpu-sgx5xx android-gpu-adreno3xx none\n"
 "    --merge-recursive-frames=<number>  merge frames between identical\n"
 "           program counters in max <number> frames) [0]\n"
 "    --num-transtab-sectors=<number> size of translated code cache [%d]\n"
@@ -627,7 +629,11 @@
                                                     VG_(clo_smc_check),
                                                     Vg_SmcAllNonFile);
 
-      else if VG_USETX_CLO (arg, "--kernel-variant", "bproc",
+      else if VG_USETX_CLO (arg, "--kernel-variant",
+                            "bproc,"
+                            "android-emulator-no-hw-tls,"
+                            "android-gpu-sgx5xx,"
+                            "android-gpu-adreno3xx",
                             VG_(clo_kernel_variant)) {}
 
       else if VG_BOOL_CLO(arg, "--dsymutil",        VG_(clo_dsymutil)) {}
diff --git a/coregrind/m_syswrap/syswrap-arm-linux.c b/coregrind/m_syswrap/syswrap-arm-linux.c
index b91edcc..18c8667 100644
--- a/coregrind/m_syswrap/syswrap-arm-linux.c
+++ b/coregrind/m_syswrap/syswrap-arm-linux.c
@@ -280,41 +280,43 @@
 static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
 {
    assign_guest_tls(tid, tlsptr);
-#if defined(ANDROID_HARDWARE_emulator)
-   /* Android emulator does not provide an hw tls register.
-      So, the tls register is emulated by the kernel.
-      This emulated value is set by the __NR_ARM_set_tls syscall.
-      The emulated value must be read by the kernel helper function
-      located at 0xffff0fe0.
-      
-      The emulated tlsptr is located at 0xffff0ff0
-      (so slightly after the kernel helper function).
-      Note that applications are not supposed to read this directly.
-      
-      For compatibility : if there is a hw tls register, the kernel
-      will put at 0xffff0fe0 the instructions to read it, so
-      as to have old applications calling the kernel helper
-      working properly.
 
-      For having emulated guest TLS working correctly with
-      Valgrind, it is needed to execute the syscall to set
-      the emulated TLS value in addition to the assignment
-      of TPIDRURO.
+   if (KernelVariantiS(KernelVariant_android_emulator_no_hw_tls,
+                       VG_(clo_kernel_variant))) {
+      /* Android emulator does not provide an hw tls register.
+         So, the tls register is emulated by the kernel.
+         This emulated value is set by the __NR_ARM_set_tls syscall.
+         The emulated value must be read by the kernel helper function
+         located at 0xffff0fe0.
+      
+         The emulated tlsptr is located at 0xffff0ff0
+         (so slightly after the kernel helper function).
+         Note that applications are not supposed to read this directly.
+      
+         For compatibility : if there is a hw tls register, the kernel
+         will put at 0xffff0fe0 the instructions to read it, so
+         as to have old applications calling the kernel helper
+         working properly.
 
-      Note: the below means that if we need thread local storage
-      for Valgrind host, then there will be a conflict between
-      the need of the guest tls and of the host tls.
-      If all the guest code would cleanly call 0xffff0fe0,
-      then we might maybe intercept this. However, at least
-      __libc_preinit reads directly 0xffff0ff0.
-   */
-   /* ??? might call the below if auxv->u.a_val & VKI_HWCAP_TLS ???
-      Unclear if real hardware having tls hw register sets
-      VKI_HWCAP_TLS. */
-   return VG_(do_syscall1) (__NR_ARM_set_tls, tlsptr);
-#else
-   return VG_(mk_SysRes_Success)( 0 );
-#endif
+         For having emulated guest TLS working correctly with
+         Valgrind, it is needed to execute the syscall to set
+         the emulated TLS value in addition to the assignment
+         of TPIDRURO.
+
+         Note: the below means that if we need thread local storage
+         for Valgrind host, then there will be a conflict between
+         the need of the guest tls and of the host tls.
+         If all the guest code would cleanly call 0xffff0fe0,
+         then we might maybe intercept this. However, at least
+         __libc_preinit reads directly 0xffff0ff0.
+      */
+      /* ??? might call the below if auxv->u.a_val & VKI_HWCAP_TLS ???
+         Unclear if real hardware having tls hw register sets
+         VKI_HWCAP_TLS. */
+      return VG_(do_syscall1) (__NR_ARM_set_tls, tlsptr);
+   } else {
+      return VG_(mk_SysRes_Success)( 0 );
+   }
 }
 
 /* ---------------------------------------------------------------------
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index 3b3218d..a4b64a8 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -7149,99 +7149,95 @@
 
    /* --- BEGIN special IOCTL handlers for specific Android hardware --- */
 
-#  if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
-      || defined(VGPV_mips32_linux_android)
+   /* BEGIN undocumented ioctls for PowerVR SGX 540 (the GPU on Nexus S) */
+   if (KernelVariantiS(KernelVariant_android_gpu_sgx5xx,
+                       VG_(clo_kernel_variant))) {
 
-#  if defined(ANDROID_HARDWARE_nexus_s)
+      if (ARG2 >= 0xC01C6700 && ARG2 <= 0xC01C67FF && ARG3 >= 0x1000) {
+         /* What's going on here: there appear to be a bunch of ioctls
+            of the form 0xC01C67xx which are undocumented, and if
+            unhandled give rise to a vast number of false positives in
+            Memcheck.
 
-   /* BEGIN undocumented ioctls for the graphics hardware (??)
-      (libpvr) on Nexus S */
-   if (ARG2 >= 0xC01C6700 && ARG2 <= 0xC01C67FF && ARG3 >= 0x1000) {
-      /* What's going on here: there appear to be a bunch of ioctls of
-         the form 0xC01C67xx which are undocumented, and if unhandled
-         give rise to a vast number of false positives in Memcheck.
+            The "normal" interpretation of an ioctl of this form would
+            be that the 3rd arg is a pointer to an area of size 0x1C
+            (28 bytes) which is filled in by the kernel.  Hence you
+            might think that "POST_MEM_WRITE(ARG3, 28)" would fix it.
+            But it doesn't.
 
-         The "normal" intrepretation of an ioctl of this form would be
-         that the 3rd arg is a pointer to an area of size 0x1C (28
-         bytes) which is filled in by the kernel.  Hence you might
-         think that "POST_MEM_WRITE(ARG3, 28)" would fix it.  But it
-         doesn't.
+            It requires POST_MEM_WRITE(ARG3, 256) to silence them.
+            One interpretation of this is that ARG3 really does point
+            to a 28 byte struct, but inside that are pointers to other
+            areas also filled in by the kernel.  If these happen to be
+            allocated just back up the stack then the 256 byte paint
+            might cover them too, somewhat indiscriminately.
 
-         It requires POST_MEM_WRITE(ARG3, 256) to silence them.  One
-         interpretation of this is that ARG3 really does point to a 28
-         byte struct, but inside that are pointers to other areas also
-         filled in by the kernel.  If these happen to be allocated
-         just back up the stack then the 256 byte paint might cover
-         them too, somewhat indiscriminately.
+            By printing out ARG3 and also the 28 bytes that it points
+            at, it's possible to guess that the 7 word structure has
+            this form
 
-         By printing out ARG3 and also the 28 bytes that it points at,
-         it's possible to guess that the 7 word structure has this form
+              0            1    2    3        4    5        6           
+              ioctl-number 0x1C ptr1 ptr1size ptr2 ptr2size aBitMask
 
-           0            1    2    3        4    5        6           
-           ioctl-number 0x1C ptr1 ptr1size ptr2 ptr2size aBitMask
-
-         Unfortunately that doesn't seem to work for some reason, so
-         stay with the blunt-instrument approach for the time being.
-      */
-      if (1) {
-         /* blunt-instrument approach */
-         if (0) VG_(printf)("QQQQQQQQQQ c01c quick hack actioned"
-                            " (%08lx, %08lx)\n", ARG2, ARG3);
-         POST_MEM_WRITE(ARG3, 256);
-      } else {
-         /* be a bit more sophisticated */
-         if (0) VG_(printf)("QQQQQQQQQQ c01c quick hack actioned"
-                            " (%08lx, %08lx) (fancy)\n", ARG2, ARG3);
-         POST_MEM_WRITE(ARG3, 28);
-         UInt* word = (UInt*)ARG3;
-         if (word && word[2] && word[3] < 0x200/*stay sane*/)
-            POST_MEM_WRITE(word[2], word[3]); // "ptr1"
-         if (word && word[4] && word[5] < 0x200/*stay sane*/)
-            POST_MEM_WRITE(word[4], word[5]); // "ptr2"
-      }
-      if (0) {
-         Int i;
-         VG_(printf)("QQQQQQQQQQ ");
-         for (i = 0; i < (0x1C/4); i++) {
-            VG_(printf)("%08x ", ((UInt*)(ARG3))[i]);
+            Unfortunately that doesn't seem to work for some reason,
+            so stay with the blunt-instrument approach for the time
+            being.
+         */
+         if (1) {
+            /* blunt-instrument approach */
+            POST_MEM_WRITE(ARG3, 256);
+         } else {
+            /* be a bit more sophisticated */
+            POST_MEM_WRITE(ARG3, 28);
+            UInt* word = (UInt*)ARG3;
+            if (word && word[2] && word[3] < 0x200/*stay sane*/)
+               POST_MEM_WRITE(word[2], word[3]); // "ptr1"
+            if (word && word[4] && word[5] < 0x200/*stay sane*/)
+               POST_MEM_WRITE(word[4], word[5]); // "ptr2"
          }
-         VG_(printf)("\n");
+         goto post_sys_ioctl__out;
       }
-      return;
    }
-   /* END Nexus S specific ioctls */
+   /* END undocumented ioctls for PowerVR SGX 540 (the GPU on Nexus S) */
 
-
-#  elif defined(ANDROID_HARDWARE_generic) || defined(ANDROID_HARDWARE_emulator)
-
-   /* BEGIN generic/emulator specific ioctls */
-   /* currently none are known */
-   /* END generic/emulator specific ioctls */
-
-
-#  else /* no ANDROID_HARDWARE_anything defined */
-
-#   warning ""
-#   warning "You need to define one the CPP symbols ANDROID_HARDWARE_blah"
-#   warning "at configure time, to tell Valgrind what hardware you are"
-#   warning "building for.  Currently known values are"
-#   warning ""
-#   warning "   ANDROID_HARDWARE_nexus_s       Samsung Nexus S"
-#   warning "   ANDROID_HARDWARE_generic       Generic device (eg, Pandaboard)"
-#   warning "   ANDROID_HARDWARE_emulator      x86 or arm emulator"
-#   warning ""
-#   warning "Make sure you exactly follow the steps in README.android."
-#   warning ""
-#   error "No CPP symbol ANDROID_HARDWARE_blah defined.  Giving up."
-
-#  endif /* cases for ANDROID_HARDWARE_blah */
-
-#  endif /* defined(VGPV_*_linux_android) */
+   /* BEGIN undocumented ioctls for Qualcomm Adreno 3xx */
+   if (KernelVariantiS(KernelVariant_android_gpu_sgx5xx,
+                       VG_(clo_kernel_variant))) {
+     if (ARG2 == 0xC00C0902) {
+         POST_MEM_WRITE(ARG3, 24); // 16 is not enough
+         goto post_sys_ioctl__out;
+     }
+   }
+   /* END undocumented ioctls for Qualcomm Adreno 3xx */
 
    /* --- END special IOCTL handlers for specific Android hardware --- */
 
    /* --- normal handling --- */
    switch (ARG2 /* request */) {
+
+   /* The Linux kernel "ion" memory allocator, used on Android.  Note:
+      this is pretty poor given that there's no pre-handling to check
+      that writable areas are addressable. */
+   case VKI_ION_IOC_ALLOC:
+      POST_MEM_WRITE(ARG3, sizeof(struct vki_ion_allocation_data));
+      break;
+   case VKI_ION_IOC_MAP:
+      POST_MEM_WRITE(ARG3, sizeof(struct vki_ion_fd_data));
+      break;
+   case VKI_ION_IOC_FREE: // is this necessary?
+      POST_MEM_WRITE(ARG3, sizeof(struct vki_ion_handle_data));
+      break;
+   case VKI_ION_IOC_SHARE:
+      break;
+   case VKI_ION_IOC_IMPORT: // is this necessary?
+      POST_MEM_WRITE(ARG3, sizeof(struct vki_ion_fd_data));
+      break;
+   case VKI_ION_IOC_SYNC:
+      break;
+   case VKI_ION_IOC_CUSTOM: // is this necessary?
+      POST_MEM_WRITE(ARG3, sizeof(struct vki_ion_custom_data));
+      break;
+
    case VKI_TCSETS:
    case VKI_TCSETSW:
    case VKI_TCSETSF:
@@ -8448,6 +8444,9 @@
       }
       break;
    }
+
+  post_sys_ioctl__out:
+   {} /* keep C compilers happy */
 }
 
 /* ---------------------------------------------------------------------
diff --git a/coregrind/pub_core_options.h b/coregrind/pub_core_options.h
index 9bf2d04..876d112 100644
--- a/coregrind/pub_core_options.h
+++ b/coregrind/pub_core_options.h
@@ -338,8 +338,12 @@
 
 /* A set of minor kernel variants,
    so they can be properly handled by m_syswrap. */
-typedef enum {
-      KernelVariant_bproc
+typedef
+   enum {
+      KernelVariant_bproc,
+      KernelVariant_android_emulator_no_hw_tls,
+      KernelVariant_android_gpu_sgx5xx,
+      KernelVariant_android_gpu_adreno3xx
    }
    KernelVariant;
 // Build mask to check or set KernelVariant a membership
diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h
index e00960c..3828c33 100644
--- a/include/vki/vki-linux.h
+++ b/include/vki/vki-linux.h
@@ -3447,6 +3447,57 @@
 #define VKI_ETHTOOL_GET_TS_INFO	0x00000041 /* Get time stamping and PHC info */
 
 //----------------------------------------------------------------------
+// From linux-3.15.8/drivers/staging/android/uapi/ion.h
+//----------------------------------------------------------------------
+
+typedef int vki_ion_user_handle_t;
+
+struct vki_ion_allocation_data {
+        vki_size_t len;
+        vki_size_t align;
+        unsigned int heap_id_mask;
+        unsigned int flags;
+        vki_ion_user_handle_t handle;
+};
+
+struct vki_ion_fd_data {
+        vki_ion_user_handle_t handle;
+        int fd;
+};
+
+struct vki_ion_handle_data {
+        vki_ion_user_handle_t handle;
+};
+
+struct vki_ion_custom_data {
+        unsigned int cmd;
+        unsigned long arg;
+};
+
+#define VKI_ION_IOC_MAGIC   'I'
+
+#define VKI_ION_IOC_ALLOC \
+   _VKI_IOWR(VKI_ION_IOC_MAGIC, 0, struct vki_ion_allocation_data)
+
+#define VKI_ION_IOC_FREE \
+   _VKI_IOWR(VKI_ION_IOC_MAGIC, 1, struct vki_ion_handle_data)
+
+#define VKI_ION_IOC_MAP \
+   _VKI_IOWR(VKI_ION_IOC_MAGIC, 2, struct vki_ion_fd_data)
+
+#define VKI_ION_IOC_SHARE \
+   _VKI_IOWR(VKI_ION_IOC_MAGIC, 4, struct vki_ion_fd_data)
+
+#define VKI_ION_IOC_IMPORT \
+   _VKI_IOWR(VKI_ION_IOC_MAGIC, 5, struct vki_ion_fd_data)
+
+#define VKI_ION_IOC_SYNC \
+   _VKI_IOWR(VKI_ION_IOC_MAGIC, 7, struct vki_ion_fd_data)
+
+#define VKI_ION_IOC_CUSTOM \
+   _VKI_IOWR(VKI_ION_IOC_MAGIC, 6, struct vki_ion_custom_data)
+
+//----------------------------------------------------------------------
 // From drivers/staging/lustre/lustre/include/lustre/lustre_user.h
 //----------------------------------------------------------------------
 
diff --git a/none/tests/cmdline1.stdout.exp b/none/tests/cmdline1.stdout.exp
index cf5794f..8d10737 100644
--- a/none/tests/cmdline1.stdout.exp
+++ b/none/tests/cmdline1.stdout.exp
@@ -92,8 +92,11 @@
          where hint is one of lax-ioctls fuse-compatible enable-outer
            no-inner-prefix no-nptl-pthread-stackcache none
     --fair-sched=no|yes|try   schedule threads fairly on multicore systems [no]
-    --kernel-variant=variant1,variant2,...  handle non-standard kernel variants [none]
-         where variant is one of bproc none
+    --kernel-variant=variant1,variant2,...
+         handle non-standard kernel variants [none]
+         where variant is one of:
+           bproc android-emulator-no-hw-tls
+           android-gpu-sgx5xx android-gpu-adreno3xx none
     --merge-recursive-frames=<number>  merge frames between identical
            program counters in max <number> frames) [0]
     --num-transtab-sectors=<number> size of translated code cache [16]
diff --git a/none/tests/cmdline2.stdout.exp b/none/tests/cmdline2.stdout.exp
index 315d0d6..2049ec5 100644
--- a/none/tests/cmdline2.stdout.exp
+++ b/none/tests/cmdline2.stdout.exp
@@ -92,8 +92,11 @@
          where hint is one of lax-ioctls fuse-compatible enable-outer
            no-inner-prefix no-nptl-pthread-stackcache none
     --fair-sched=no|yes|try   schedule threads fairly on multicore systems [no]
-    --kernel-variant=variant1,variant2,...  handle non-standard kernel variants [none]
-         where variant is one of bproc none
+    --kernel-variant=variant1,variant2,...
+         handle non-standard kernel variants [none]
+         where variant is one of:
+           bproc android-emulator-no-hw-tls
+           android-gpu-sgx5xx android-gpu-adreno3xx none
     --merge-recursive-frames=<number>  merge frames between identical
            program counters in max <number> frames) [0]
     --num-transtab-sectors=<number> size of translated code cache [16]