From a0f53e1dbb3851bb0f0efcfdbd565b05e4be9cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Thu, 23 Aug 2012 18:10:57 +0200 Subject: [PATCH 1/2] ARM: qemu related workarounds in cpu features detection code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was ported from meta-oe's patch [1]. The original pixman patch is found at [2]. [1] http://cgit.openembedded.org/meta-openembedded/tree/meta-oe/recipes-graphics/xorg-lib/pixman-0.26.2/0001-ARM-qemu-related-workarounds-in-cpu-features-detecti.patch [2] http://lists.freedesktop.org/archives/pixman/2011-January/000906.html Upstream-Status: Inappropriate [other] qemu fix Signed-off-by: Andreas Müller --- pixman/pixman-arm.c | 82 ++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 65 insertions(+), 17 deletions(-) diff --git a/pixman/pixman-arm.c b/pixman/pixman-arm.c index 23374e4..d98bda6 100644 --- a/pixman/pixman-arm.c +++ b/pixman/pixman-arm.c @@ -129,16 +129,35 @@ detect_cpu_features (void) #include #include #include +#include #include #include #include +/* + * The whole CPU capabilities detection is a bit ugly: when running in + * userspace qemu, we see /proc/self/auxv from the host system. To make + * everything even worse, the size of each value is 64-bit when running + * on a 64-bit host system. So the data is totally bogus because we expect + * 32-bit values. As AT_PLATFORM value is used as a pointer, it may cause + * segfault (null pointer dereference on x86-64 host). So in order to be + * on a safe side, we require that AT_PLATFORM value is found only once, + * and it has non-zero value (this is still not totally reliable for a big + * endian 64-bit host system running qemu and may theoretically fail). + */ +#define ARM_HWCAP_VFP 64 +#define ARM_HWCAP_IWMMXT 512 +#define ARM_HWCAP_NEON 4096 + static arm_cpu_features_t detect_cpu_features (void) { arm_cpu_features_t features = 0; Elf32_auxv_t aux; int fd; + uint32_t hwcap = 0; + const char *plat = NULL; + int plat_cnt = 0; fd = open ("/proc/self/auxv", O_RDONLY); if (fd >= 0) @@ -147,32 +166,61 @@ detect_cpu_features (void) { if (aux.a_type == AT_HWCAP) { - uint32_t hwcap = aux.a_un.a_val; - - /* hardcode these values to avoid depending on specific - * versions of the hwcap header, e.g. HWCAP_NEON - */ - if ((hwcap & 64) != 0) - features |= ARM_VFP; - if ((hwcap & 512) != 0) - features |= ARM_IWMMXT; - /* this flag is only present on kernel 2.6.29 */ - if ((hwcap & 4096) != 0) - features |= ARM_NEON; + hwcap = aux.a_un.a_val; } else if (aux.a_type == AT_PLATFORM) { - const char *plat = (const char*) aux.a_un.a_val; - - if (strncmp (plat, "v7l", 3) == 0) + plat = (const char*) aux.a_un.a_val; + plat_cnt++; + } + } + close (fd); + if (plat == NULL || plat_cnt != 1 || *plat != 'v') + { + /* + * Something seems to be really wrong, most likely we are + * running under qemu. Let's use machine type from "uname" for + * CPU capabilities detection: + * http://www.mail-archive.com/qemu-devel at nongnu.org/msg22212.html + */ + struct utsname u; + hwcap = 0; /* clear hwcap, because it is bogus */ + if (uname (&u) == 0) + { + if (strcmp (u.machine, "armv7l") == 0) + { features |= (ARM_V7 | ARM_V6); - else if (strncmp (plat, "v6l", 3) == 0) + hwcap |= ARM_HWCAP_VFP; /* qemu is supposed to emulate vfp */ + hwcap |= ARM_HWCAP_NEON; /* qemu is supposed to emulate neon */ + } + else if (strcmp (u.machine, "armv6l") == 0) + { features |= ARM_V6; + hwcap |= ARM_HWCAP_VFP; /* qemu is supposed to emulate vfp */ + } } } - close (fd); + else if (strncmp (plat, "v7l", 3) == 0) + { + features |= (ARM_V7 | ARM_V6); + } + else if (strncmp (plat, "v6l", 3) == 0) + { + features |= ARM_V6; + } } + /* hardcode these values to avoid depending on specific + * versions of the hwcap header, e.g. HWCAP_NEON + */ + if ((hwcap & ARM_HWCAP_VFP) != 0) + features |= ARM_VFP; + if ((hwcap & ARM_HWCAP_IWMMXT) != 0) + features |= ARM_IWMMXT; + /* this flag is only present on kernel 2.6.29 */ + if ((hwcap & ARM_HWCAP_NEON) != 0) + features |= ARM_NEON; + return features; } -- 1.7.6.5