blob: 14fe73b1774e3dc6cc2f05143127684eee1ea936 [file] [log] [blame]
xf.libfc6e712025-02-07 01:54:34 -08001/* Check __ppc_get_hwcap() and __ppc_get_at_plaftorm() functionality.
2 Copyright (C) 2015-2016 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
18
19/* Tests if the hwcap, hwcap2 and platform data are stored in the TCB. */
20
21#include <inttypes.h>
22#include <stdio.h>
23#include <stdint.h>
24#include <pthread.h>
25
26#include <sys/auxv.h>
27
28#include <dl-procinfo.h>
29
30#ifndef STATIC_TST_HWCAP
31#undef PROCINFO_DECL
32#include <dl-procinfo.c>
33#endif
34
35/* Offsets copied from tcb-offsets.h. */
36
37#ifdef __powerpc64__
38# define __TPREG "r13"
39# define __HWCAPOFF -28776
40# define __ATPLATOFF -28764
41#else
42# define __TPREG "r2"
43# define __HWCAPOFF -28736
44# define __HWCAP2OFF -28732
45# define __ATPLATOFF -28724
46#endif
47
48uint64_t check_tcbhwcap (long tid)
49{
50
51 uint32_t tcb_at_platform, at_platform;
52 uint64_t hwcap, hwcap2, tcb_hwcap;
53 const char *at_platform_string;
54
55 /* Testing if the hwcap/hwcap2 data is correctly initialized by
56 TLS_TP_INIT. */
57
58 register unsigned long __tp __asm__ (__TPREG);
59
60#ifdef __powerpc64__
61 __asm__ ("ld %0,%1(%2)\n"
62 : "=r" (tcb_hwcap)
63 : "i" (__HWCAPOFF), "b" (__tp));
64#else
65 uint64_t h1, h2;
66
67 __asm__ ("lwz %0,%1(%2)\n"
68 : "=r" (h1)
69 : "i" (__HWCAPOFF), "b" (__tp));
70 __asm__ ("lwz %0,%1(%2)\n"
71 : "=r" (h2)
72 : "i" (__HWCAP2OFF), "b" (__tp));
73 tcb_hwcap = (h1 >> 32) << 32 | (h2 >> 32);
74#endif
75
76 hwcap = getauxval (AT_HWCAP);
77 hwcap2 = getauxval (AT_HWCAP2);
78
79 /* hwcap contains only the latest supported ISA, the code checks which is
80 and fills the previous supported ones. This is necessary because the
81 same is done in hwcapinfo.c when setting the values that are copied to
82 the TCB. */
83
84 if (hwcap2 & PPC_FEATURE2_ARCH_2_07)
85 hwcap |= PPC_FEATURE_ARCH_2_06
86 | PPC_FEATURE_ARCH_2_05
87 | PPC_FEATURE_POWER5_PLUS
88 | PPC_FEATURE_POWER5
89 | PPC_FEATURE_POWER4;
90 else if (hwcap & PPC_FEATURE_ARCH_2_06)
91 hwcap |= PPC_FEATURE_ARCH_2_05
92 | PPC_FEATURE_POWER5_PLUS
93 | PPC_FEATURE_POWER5
94 | PPC_FEATURE_POWER4;
95 else if (hwcap & PPC_FEATURE_ARCH_2_05)
96 hwcap |= PPC_FEATURE_POWER5_PLUS
97 | PPC_FEATURE_POWER5
98 | PPC_FEATURE_POWER4;
99 else if (hwcap & PPC_FEATURE_POWER5_PLUS)
100 hwcap |= PPC_FEATURE_POWER5
101 | PPC_FEATURE_POWER4;
102 else if (hwcap & PPC_FEATURE_POWER5)
103 hwcap |= PPC_FEATURE_POWER4;
104
105 hwcap = (hwcap << 32) + hwcap2;
106
107 if ( tcb_hwcap != hwcap )
108 {
109 printf ("FAIL: __ppc_get_hwcap() - HWCAP is %" PRIx64 ". Should be %"
110 PRIx64 " for thread %ld.\n", tcb_hwcap, hwcap, tid);
111 return 1;
112 }
113
114 /* Same test for the platform number. */
115 __asm__ ("lwz %0,%1(%2)\n"
116 : "=r" (tcb_at_platform)
117 : "i" (__ATPLATOFF), "b" (__tp));
118
119 at_platform_string = (const char *) getauxval (AT_PLATFORM);
120 at_platform = _dl_string_platform (at_platform_string);
121
122 if ( tcb_at_platform != at_platform )
123 {
124 printf ("FAIL: __ppc_get_at_platform() - AT_PLATFORM is %x. Should be %x"
125 " for thread %ld\n", tcb_at_platform, at_platform, tid);
126 return 1;
127 }
128
129 return 0;
130}
131
132void *t1 (void *tid)
133{
134 if (check_tcbhwcap ((long) tid))
135 {
136 pthread_exit (tid);
137 }
138
139 pthread_exit (NULL);
140
141}
142
143static int
144do_test (void)
145{
146
147 pthread_t threads[2];
148 pthread_attr_t attr;
149 pthread_attr_init (&attr);
150 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
151 void *status;
152
153 long i = 0;
154
155 /* Check for main. */
156 if (check_tcbhwcap (i))
157 {
158 return 1;
159 }
160
161 /* Check for other thread. */
162 i++;
163 if (pthread_create (&threads[i], &attr, t1, (void *)i))
164 {
165 printf ("FAIL: error creating thread %ld.\n", i);
166 return 1;
167 }
168
169 pthread_attr_destroy (&attr);
170 if (pthread_join (threads[i], &status))
171 {
172 printf ("FAIL: error joining thread %ld.\n", i);
173 return 1;
174 }
175 if (status)
176 {
177 return 1;
178 }
179
180 printf("PASS: HWCAP, HWCAP2 and AT_PLATFORM are correctly set in the TCB for"
181 " all threads.\n");
182
183 pthread_exit (NULL);
184
185}
186
187#define TEST_FUNCTION do_test ()
188#include "../test-skeleton.c"