|
1 /* |
|
2 * Copyright © 2000 SuSE, Inc. |
|
3 * Copyright © 2007 Red Hat, Inc. |
|
4 * |
|
5 * Permission to use, copy, modify, distribute, and sell this software and its |
|
6 * documentation for any purpose is hereby granted without fee, provided that |
|
7 * the above copyright notice appear in all copies and that both that |
|
8 * copyright notice and this permission notice appear in supporting |
|
9 * documentation, and that the name of SuSE not be used in advertising or |
|
10 * publicity pertaining to distribution of the software without specific, |
|
11 * written prior permission. SuSE makes no representations about the |
|
12 * suitability of this software for any purpose. It is provided "as is" |
|
13 * without express or implied warranty. |
|
14 * |
|
15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL |
|
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE |
|
17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|
19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
21 */ |
|
22 #ifdef HAVE_CONFIG_H |
|
23 #include <config.h> |
|
24 #endif |
|
25 |
|
26 #include "pixman-private.h" |
|
27 |
|
28 #ifdef USE_VMX |
|
29 |
|
30 /* The CPU detection code needs to be in a file not compiled with |
|
31 * "-maltivec -mabi=altivec", as gcc would try to save vector register |
|
32 * across function calls causing SIGILL on cpus without Altivec/vmx. |
|
33 */ |
|
34 #ifdef __APPLE__ |
|
35 #include <sys/sysctl.h> |
|
36 |
|
37 static pixman_bool_t |
|
38 pixman_have_vmx (void) |
|
39 { |
|
40 int error, have_vmx; |
|
41 size_t length = sizeof(have_vmx); |
|
42 |
|
43 error = sysctlbyname ("hw.optional.altivec", &have_vmx, &length, NULL, 0); |
|
44 |
|
45 if (error) |
|
46 return FALSE; |
|
47 |
|
48 return have_vmx; |
|
49 } |
|
50 |
|
51 #elif defined (__OpenBSD__) |
|
52 #include <sys/param.h> |
|
53 #include <sys/sysctl.h> |
|
54 #include <machine/cpu.h> |
|
55 |
|
56 static pixman_bool_t |
|
57 pixman_have_vmx (void) |
|
58 { |
|
59 int error, have_vmx; |
|
60 int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC }; |
|
61 size_t length = sizeof(have_vmx); |
|
62 |
|
63 error = sysctl (mib, 2, &have_vmx, &length, NULL, 0); |
|
64 |
|
65 if (error != 0) |
|
66 return FALSE; |
|
67 |
|
68 return have_vmx; |
|
69 } |
|
70 |
|
71 #elif defined (__linux__) |
|
72 |
|
73 #include <sys/types.h> |
|
74 #include <sys/stat.h> |
|
75 #include <fcntl.h> |
|
76 #include <unistd.h> |
|
77 #include <stdio.h> |
|
78 #include <linux/auxvec.h> |
|
79 #include <asm/cputable.h> |
|
80 |
|
81 static pixman_bool_t |
|
82 pixman_have_vmx (void) |
|
83 { |
|
84 int have_vmx = FALSE; |
|
85 int fd; |
|
86 struct |
|
87 { |
|
88 unsigned long type; |
|
89 unsigned long value; |
|
90 } aux; |
|
91 |
|
92 fd = open ("/proc/self/auxv", O_RDONLY); |
|
93 if (fd >= 0) |
|
94 { |
|
95 while (read (fd, &aux, sizeof (aux)) == sizeof (aux)) |
|
96 { |
|
97 if (aux.type == AT_HWCAP && (aux.value & PPC_FEATURE_HAS_ALTIVEC)) |
|
98 { |
|
99 have_vmx = TRUE; |
|
100 break; |
|
101 } |
|
102 } |
|
103 |
|
104 close (fd); |
|
105 } |
|
106 |
|
107 return have_vmx; |
|
108 } |
|
109 |
|
110 #else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */ |
|
111 #include <signal.h> |
|
112 #include <setjmp.h> |
|
113 |
|
114 static jmp_buf jump_env; |
|
115 |
|
116 static void |
|
117 vmx_test (int sig, |
|
118 siginfo_t *si, |
|
119 void * unused) |
|
120 { |
|
121 longjmp (jump_env, 1); |
|
122 } |
|
123 |
|
124 static pixman_bool_t |
|
125 pixman_have_vmx (void) |
|
126 { |
|
127 struct sigaction sa, osa; |
|
128 int jmp_result; |
|
129 |
|
130 sa.sa_flags = SA_SIGINFO; |
|
131 sigemptyset (&sa.sa_mask); |
|
132 sa.sa_sigaction = vmx_test; |
|
133 sigaction (SIGILL, &sa, &osa); |
|
134 jmp_result = setjmp (jump_env); |
|
135 if (jmp_result == 0) |
|
136 { |
|
137 asm volatile ( "vor 0, 0, 0" ); |
|
138 } |
|
139 sigaction (SIGILL, &osa, NULL); |
|
140 return (jmp_result == 0); |
|
141 } |
|
142 |
|
143 #endif /* __APPLE__ */ |
|
144 #endif /* USE_VMX */ |
|
145 |
|
146 pixman_implementation_t * |
|
147 _pixman_ppc_get_implementations (pixman_implementation_t *imp) |
|
148 { |
|
149 #ifdef USE_VMX |
|
150 if (!_pixman_disabled ("vmx") && pixman_have_vmx ()) |
|
151 imp = _pixman_implementation_create_vmx (imp); |
|
152 #endif |
|
153 |
|
154 return imp; |
|
155 } |