aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-graphics/xorg-lib/pixman-0.27.2/0001-ARM-qemu-related-workarounds-in-cpu-features-detecti.patch
blob: 8a1c524a8329d15448a1b7a16820c723b5372d0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
From d140e69c1d76ed61d1feb53b79820951707ee5a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20M=C3=BCller?= <schnitzeltony@googlemail.com>
Date: Sun, 19 Aug 2012 15:15:45 +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]

[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

Upstream-Status: Inappropriate [other] qemu fix

Signed-off-by: Andreas Müller <schnitzeltony@googlemail.com>
---
 pixman/pixman-arm.c |   74 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 69 insertions(+), 5 deletions(-)

diff --git a/pixman/pixman-arm.c b/pixman/pixman-arm.c
index 23374e4..d0771fd 100644
--- a/pixman/pixman-arm.c
+++ b/pixman/pixman-arm.c
@@ -129,16 +129,35 @@ detect_cpu_features (void)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
+#include <sys/utsname.h>
 #include <fcntl.h>
 #include <string.h>
 #include <elf.h>
 
+/*
+ * 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,22 +166,23 @@ detect_cpu_features (void)
 	{
 	    if (aux.a_type == AT_HWCAP)
 	    {
-		uint32_t hwcap = aux.a_un.a_val;
+		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)
+		if ((hwcap & ARM_HWCAP_VFP) != 0)
 		    features |= ARM_VFP;
-		if ((hwcap & 512) != 0)
+		if ((hwcap & ARM_HWCAP_IWMMXT) != 0)
 		    features |= ARM_IWMMXT;
 		/* this flag is only present on kernel 2.6.29 */
-		if ((hwcap & 4096) != 0)
+		if ((hwcap & ARM_HWCAP_NEON) != 0)
 		    features |= ARM_NEON;
 	    }
 	    else if (aux.a_type == AT_PLATFORM)
 	    {
-		const char *plat = (const char*) aux.a_un.a_val;
+		plat = (const char*) aux.a_un.a_val;
+		plat_cnt++;
 
 		if (strncmp (plat, "v7l", 3) == 0)
 		    features |= (ARM_V7 | ARM_V6);
@@ -171,8 +191,52 @@ detect_cpu_features (void)
 	    }
 	}
 	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);
+		    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 */
+		}
+	    }
+	}
+	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;
+    if ((hwcap & ARM_HWCAP_NEON) != 0)
+        features |= ARM_NEON;
+
     return features;
 }
 
-- 
1.7.4.4