pixman-ppc.c (4004B)
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 <pixman-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 (__FreeBSD__) 72 #include <machine/cpu.h> 73 #include <sys/auxv.h> 74 75 static pixman_bool_t 76 pixman_have_vmx (void) 77 { 78 79 unsigned long cpufeatures; 80 int have_vmx; 81 82 if (elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures))) 83 return FALSE; 84 85 have_vmx = cpufeatures & PPC_FEATURE_HAS_ALTIVEC; 86 return have_vmx; 87 } 88 89 #elif defined (__linux__) 90 91 #include <sys/types.h> 92 #include <sys/stat.h> 93 #include <fcntl.h> 94 #include <unistd.h> 95 #include <stdio.h> 96 #include <linux/auxvec.h> 97 #include <asm/cputable.h> 98 99 static pixman_bool_t 100 pixman_have_vmx (void) 101 { 102 int have_vmx = FALSE; 103 int fd; 104 struct 105 { 106 unsigned long type; 107 unsigned long value; 108 } aux; 109 110 fd = open ("/proc/self/auxv", O_RDONLY); 111 if (fd >= 0) 112 { 113 while (read (fd, &aux, sizeof (aux)) == sizeof (aux)) 114 { 115 if (aux.type == AT_HWCAP && (aux.value & PPC_FEATURE_HAS_ALTIVEC)) 116 { 117 have_vmx = TRUE; 118 break; 119 } 120 } 121 122 close (fd); 123 } 124 125 return have_vmx; 126 } 127 128 #else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */ 129 #include <signal.h> 130 #include <setjmp.h> 131 132 static jmp_buf jump_env; 133 134 static void 135 vmx_test (int sig, 136 siginfo_t *si, 137 void * unused) 138 { 139 longjmp (jump_env, 1); 140 } 141 142 static pixman_bool_t 143 pixman_have_vmx (void) 144 { 145 struct sigaction sa, osa; 146 int jmp_result; 147 148 sa.sa_flags = SA_SIGINFO; 149 sigemptyset (&sa.sa_mask); 150 sa.sa_sigaction = vmx_test; 151 sigaction (SIGILL, &sa, &osa); 152 jmp_result = setjmp (jump_env); 153 if (jmp_result == 0) 154 { 155 asm volatile ( "vor 0, 0, 0" ); 156 } 157 sigaction (SIGILL, &osa, NULL); 158 return (jmp_result == 0); 159 } 160 161 #endif /* __APPLE__ */ 162 #endif /* USE_VMX */ 163 164 pixman_implementation_t * 165 _pixman_ppc_get_implementations (pixman_implementation_t *imp) 166 { 167 #ifdef USE_VMX 168 if (!_pixman_disabled ("vmx") && pixman_have_vmx ()) 169 imp = _pixman_implementation_create_vmx (imp); 170 #endif 171 172 return imp; 173 }