1 /* Test the implementation of __ppc_set_ppr_* functions.
2    Copyright (C) 2017-2022 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    <https://www.gnu.org/licenses/>.  */
18 
19 #include <inttypes.h>
20 #include <stdio.h>
21 #include <stdint.h>
22 #include <sys/auxv.h>
23 
24 #include <sys/platform/ppc.h>
25 
26 #include <support/test-driver.h>
27 
28 #ifdef __powerpc64__
29   typedef uint64_t ppr_t;
30 # define MFPPR "mfppr"
31   /* The thread priority value is obtained from bits 11:13.  */
32 # define EXTRACT_THREAD_PRIORITY(x) ((x >> 50) & 7)
33 #else
34   typedef uint32_t ppr_t;
35 # define MFPPR "mfppr32"
36   /* For 32-bit, the upper 32 bits of the Program Priority Register (PPR)
37      are used, so the thread priority value is obtained from bits 43:46.  */
38 # define EXTRACT_THREAD_PRIORITY(x) ((x >> 18) & 7)
39 #endif /* !__powerpc64__ */
40 
41 /* Read the thread priority value set in the PPR.  */
42 static __inline__ ppr_t
get_thread_priority(void)43 get_thread_priority (void)
44 {
45   /* Read the PPR.  */
46   ppr_t ppr;
47   asm volatile (".machine push; .machine power7; "MFPPR" %0; .machine pop"
48 		: "=r"(ppr));
49   /* Return the thread priority value.  */
50   return EXTRACT_THREAD_PRIORITY (ppr);
51 }
52 
53 /* Check the thread priority bits of PPR are set as expected. */
54 uint8_t
check_thread_priority(uint8_t expected)55 check_thread_priority (uint8_t expected)
56 {
57   ppr_t actual = get_thread_priority ();
58 
59   if (actual != expected)
60     {
61       printf ("FAIL: Expected %"PRIu8" got %"PRIuMAX".\n", expected,
62 	      (uintmax_t) actual);
63       return 1;
64     }
65   printf ("PASS: Thread priority set to %"PRIu8" correctly.\n", expected);
66   return 0;
67 }
68 
69 /* The Power ISA 2.06 allows the following thread priorities for any
70    problem state program: low (2), medium low (3), and medium (4).
71    Power ISA 2.07b added very low (1).
72    Check whether the values set by __ppc_set_ppr_* are correct.  */
73 static int
do_test(void)74 do_test (void)
75 {
76   /* Check for the minimum required Power ISA to run these tests.  */
77   if ((getauxval (AT_HWCAP) & PPC_FEATURE_ARCH_2_06) == 0)
78     {
79       printf ("Requires an environment that implements the Power ISA version"
80               " 2.06 or greater.\n");
81       return EXIT_UNSUPPORTED;
82     }
83 
84   uint8_t rc = 0;
85 
86 #ifdef _ARCH_PWR8
87   __ppc_set_ppr_very_low ();
88   rc |= check_thread_priority (1);
89 #endif /* _ARCH_PWR8 */
90 
91   __ppc_set_ppr_low ();
92   rc |= check_thread_priority (2);
93 
94   __ppc_set_ppr_med_low ();
95   rc |= check_thread_priority (3);
96 
97   __ppc_set_ppr_med ();
98   rc |= check_thread_priority (4);
99 
100   return rc;
101 }
102 
103 #include <support/test-driver.c>
104