]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/powerpc/ofw/cas.c
ident(1): Normalizing date format
[FreeBSD/FreeBSD.git] / stand / powerpc / ofw / cas.c
1 /*-
2  * Copyright (c) 2019 Leandro Lupori
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include <openfirm.h>
30 #include <stand.h>
31
32 /* PVR */
33 #define PVR_CPU_P8E             0x004b0000
34 #define PVR_CPU_P8NVL           0x004c0000
35 #define PVR_CPU_P8              0x004d0000
36 #define PVR_CPU_P9              0x004e0000
37 #define PVR_CPU_MASK            0xffff0000
38
39 #define PVR_ISA_207             0x0f000004
40 #define PVR_ISA_300             0x0f000005
41 #define PVR_ISA_MASK            0xffffffff
42
43 /* loader version of kernel's CPU_MAXSIZE */
44 #define MAX_CPUS                ((uint32_t)256u)
45
46 /* Option Vectors' settings */
47
48 /* length of ignored OV */
49 #define OV_IGN_LEN              0
50
51 /* byte 1 (of any OV) */
52 #define OV_IGN                  0x80
53
54 /* Option Vector 5 */
55
56 /* byte 2 */
57 #define OV5_LPAR                0x80
58 #define OV5_SPLPAR              0x40
59 #define OV5_DRMEM               0x20
60 #define OV5_LP                  0x10
61 #define OV5_ALPHA_PART          0x08
62 #define OV5_DMA_DELAY           0x04
63 #define OV5_DONATE_CPU          0x02
64 #define OV5_MSI                 0x01
65
66 /* 9-12: max cpus */
67 #define OV5_MAX_CPUS(n)         ((MAX_CPUS >> (3*8 - (n)*8)) & 0xff)
68
69 /* 13-14: LoPAPR Level */
70 #define LOPAPR_LEVEL            0x0101  /* 1.1 */
71 #define OV5_LOPAPR_LEVEL(n)     ((LOPAPR_LEVEL >> (8 - (n)*8)) & 0xff)
72
73 /* byte 17: Platform Facilities */
74 #define OV5_RNG                 0x80
75 #define OV5_COMP_ENG            0x40
76 #define OV5_ENC_ENG             0x20
77
78 /* byte 21: Sub-Processors */
79 #define OV5_NO_SUBPROCS         0
80 #define OV5_SUBPROCS            1
81
82 /* byte 23: interrupt controller */
83 #define OV5_INTC_XICS           0
84
85 /* byte 24: MMU */
86 #define OV5_MMU_HPT             0
87
88 /* byte 25: HPT MMU Extensions */
89 #define OV5_HPT_EXT_NONE        0
90
91 /* byte 26: Radix MMU Extensions */
92 #define OV5_RPT_EXT_NONE        0
93
94
95 struct pvr {
96         uint32_t        mask;
97         uint32_t        val;
98 };
99
100 struct opt_vec_ignore {
101         char    data[2];
102 } __packed;
103
104 struct opt_vec4 {
105         char data[3];
106 } __packed;
107
108 struct opt_vec5 {
109         char data[27];
110 } __packed;
111
112 static struct ibm_arch_vec {
113         struct pvr              pvr_list[7];
114         uint8_t                 num_opts;
115         struct opt_vec_ignore   vec1;
116         struct opt_vec_ignore   vec2;
117         struct opt_vec_ignore   vec3;
118         struct opt_vec4         vec4;
119         struct opt_vec5         vec5;
120 } __packed ibm_arch_vec = {
121         /* pvr_list */ {
122                 { PVR_CPU_MASK, PVR_CPU_P8 },           /* POWER8 */
123                 { PVR_CPU_MASK, PVR_CPU_P8E },          /* POWER8E */
124                 { PVR_CPU_MASK, PVR_CPU_P8NVL },        /* POWER8NVL */
125                 { PVR_CPU_MASK, PVR_CPU_P9 },           /* POWER9 */
126                 { PVR_ISA_MASK, PVR_ISA_207 },          /* All ISA 2.07 */
127                 { PVR_ISA_MASK, PVR_ISA_300 },          /* All ISA 3.00 */
128                 { 0, 0xffffffffu }                      /* terminator */
129         },
130         4,      /* num_opts (4 actually means 5 option vectors) */
131         { OV_IGN_LEN, OV_IGN },         /* OV1 */
132         { OV_IGN_LEN, OV_IGN },         /* OV2 */
133         { OV_IGN_LEN, OV_IGN },         /* OV3 */
134         /* OV4 (can't be ignored) */ {
135                 sizeof(struct opt_vec4) - 2,    /* length (n-2) */
136                 0,
137                 10 /* Minimum VP entitled capacity percentage * 100
138                     * (if absent assume 10%) */
139         },
140         /* OV5 */ {
141                 sizeof(struct opt_vec5) - 2,    /* length (n-2) */
142                 0,                              /* don't ignore */
143                 OV5_LPAR | OV5_SPLPAR | OV5_LP | OV5_MSI,
144                 0,
145                 0,      /* Cooperative Memory Over-commitment */
146                 0,      /* Associativity Information Option */
147                 0,      /* Binary Option Controls */
148                 0,      /* Reserved */
149                 0,      /* Reserved */
150                 OV5_MAX_CPUS(0),
151                 OV5_MAX_CPUS(1),                /* 10 */
152                 OV5_MAX_CPUS(2),
153                 OV5_MAX_CPUS(3),
154                 OV5_LOPAPR_LEVEL(0),
155                 OV5_LOPAPR_LEVEL(1),
156                 0,      /* Reserved */
157                 0,      /* Reserved */
158                 0,      /* Platform Facilities */
159                 0,      /* Reserved */
160                 0,      /* Reserved */
161                 0,      /* Reserved */          /* 20 */
162                 OV5_NO_SUBPROCS,
163                 0,      /* DRMEM_V2 */
164                 OV5_INTC_XICS,
165                 OV5_MMU_HPT,
166                 OV5_HPT_EXT_NONE,
167                 OV5_RPT_EXT_NONE
168         }
169 };
170
171 static __inline register_t
172 mfpvr(void)
173 {
174         register_t value;
175
176         __asm __volatile ("mfpvr %0" : "=r"(value));
177
178         return (value);
179 }
180
181 static __inline int
182 ppc64_hv(void)
183 {
184         int hv;
185
186         /* PSL_HV is bit 3 of 64-bit MSR */
187         __asm __volatile ("mfmsr %0\n\t"
188                 "rldicl %0,%0,4,63" : "=r"(hv));
189
190         return (hv);
191 }
192
193 int
194 ppc64_cas(void)
195 {
196         int rc;
197         ihandle_t ihandle;
198         cell_t err;
199
200         /* Perform CAS only for POWER8 and later cores */
201         switch (mfpvr() & PVR_CPU_MASK) {
202                 case PVR_CPU_P8:
203                 case PVR_CPU_P8E:
204                 case PVR_CPU_P8NVL:
205                 case PVR_CPU_P9:
206                         break;
207                 default:
208                         return (0);
209         }
210
211         /* Skip CAS when running on PowerNV */
212         if (ppc64_hv())
213                 return (0);
214
215         ihandle = OF_open("/");
216         if (ihandle == -1) {
217                 printf("cas: failed to open / node\n");
218                 return (-1);
219         }
220
221         if (rc = OF_call_method("ibm,client-architecture-support",
222             ihandle, 1, 1, &ibm_arch_vec, &err))
223                 printf("cas: failed to call CAS method\n");
224         else if (err) {
225                 printf("cas: error: 0x%08lX\n", err);
226                 rc = -1;
227         }
228
229         OF_close(ihandle);
230         return (rc);
231 }