Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/powerpc/ofw/cas.c
107787 views
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 <openfirm.h>
27
#include <stand.h>
28
29
#include <sys/endian.h>
30
31
/* #define CAS_DEBUG */
32
#ifdef CAS_DEBUG
33
#define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
34
#else
35
#define DPRINTF(fmt, ...) do { ; } while (0)
36
#endif
37
38
/* PVR */
39
#define PVR_CPU_P6 0x003e0000
40
#define PVR_CPU_P7 0x003f0000
41
#define PVR_CPU_P7PLUS 0x004a0000
42
#define PVR_CPU_P8E 0x004b0000
43
#define PVR_CPU_P8NVL 0x004c0000
44
#define PVR_CPU_P8 0x004d0000
45
#define PVR_CPU_P9 0x004e0000
46
#define PVR_CPU_P10 0x00800000
47
#define PVR_CPU_P11 0x00820000
48
#define PVR_CPU_MASK 0xffff0000
49
50
#define PVR_ISA_207 0x0f000004
51
#define PVR_ISA_300 0x0f000005
52
#define PVR_ISA_31 0x0f000006
53
#define PVR_ISA_MASK 0xffffffff
54
55
/* loader version of kernel's CPU_MAXSIZE */
56
#define MAX_CPUS ((uint32_t)256u)
57
58
/* Option Vectors' settings */
59
60
/* length of ignored OV */
61
#define OV_IGN_LEN 0
62
63
/* byte 1 (of any OV) */
64
#define OV_IGN 0x80
65
66
/* Option Vector 5 */
67
68
/* byte 2 */
69
#define OV5_LPAR 0x80
70
#define OV5_SPLPAR 0x40
71
#define OV5_DRMEM 0x20
72
#define OV5_LP 0x10
73
#define OV5_ALPHA_PART 0x08
74
#define OV5_DMA_DELAY 0x04
75
#define OV5_DONATE_CPU 0x02
76
#define OV5_MSI 0x01
77
78
/* 9-12: max cpus */
79
#define OV5_MAX_CPUS(n) ((MAX_CPUS >> (3*8 - (n)*8)) & 0xff)
80
81
/* 13-14: LoPAPR Level */
82
#define LOPAPR_LEVEL 0x0101 /* 1.1 */
83
#define OV5_LOPAPR_LEVEL(n) ((LOPAPR_LEVEL >> (8 - (n)*8)) & 0xff)
84
85
/* byte 17: Platform Facilities */
86
#define OV5_RNG 0x80
87
#define OV5_COMP_ENG 0x40
88
#define OV5_ENC_ENG 0x20
89
90
/* byte 21: Sub-Processors */
91
#define OV5_NO_SUBPROCS 0
92
#define OV5_SUBPROCS 1
93
94
/* byte 23: interrupt controller */
95
#define OV5_INTC_XICS 0
96
97
/* byte 24: MMU */
98
#define OV5_MMU_INDEX 24
99
#define OV5_MMU_HPT 0
100
#define OV5_MMU_RADIX 0x40
101
#define OV5_MMU_EITHER 0x80
102
#define OV5_MMU_DYNAMIC 0xc0
103
104
/* byte 25: HPT MMU Extensions */
105
#define OV5_HPT_EXT_INDEX 25
106
#define OV5_HPT_GTSE 0x40
107
108
/* byte 26: Radix MMU Extensions */
109
#define OV5_RADIX_EXT_INDEX 26
110
#define OV5_RADIX_GTSE 0x40
111
112
113
struct pvr {
114
uint32_t mask;
115
uint32_t val;
116
};
117
118
struct opt_vec_ignore {
119
char data[2];
120
} __packed;
121
122
struct opt_vec4 {
123
char data[3];
124
} __packed;
125
126
struct opt_vec5 {
127
char data[27];
128
} __packed;
129
130
static struct ibm_arch_vec {
131
struct pvr pvr_list[13];
132
uint8_t num_opts;
133
struct opt_vec_ignore vec1;
134
struct opt_vec_ignore vec2;
135
struct opt_vec_ignore vec3;
136
struct opt_vec4 vec4;
137
struct opt_vec5 vec5;
138
} __packed ibm_arch_vec = {
139
/* pvr_list */ {
140
{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P6) },
141
{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P7) },
142
{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P7PLUS) },
143
{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8) },
144
{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8E) },
145
{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P8NVL) },
146
{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P9) },
147
{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P10) },
148
{ htobe32(PVR_CPU_MASK), htobe32(PVR_CPU_P11) },
149
{ htobe32(PVR_ISA_MASK), htobe32(PVR_ISA_207) },
150
{ htobe32(PVR_ISA_MASK), htobe32(PVR_ISA_300) },
151
{ htobe32(PVR_ISA_MASK), htobe32(PVR_ISA_31) },
152
{ 0, 0xffffffffu } /* terminator */
153
},
154
4, /* num_opts (4 actually means 5 option vectors) */
155
{ OV_IGN_LEN, OV_IGN }, /* OV1 */
156
{ OV_IGN_LEN, OV_IGN }, /* OV2 */
157
{ OV_IGN_LEN, OV_IGN }, /* OV3 */
158
/* OV4 (can't be ignored) */ {
159
sizeof(struct opt_vec4) - 2, /* length (n-2) */
160
0,
161
10 /* Minimum VP entitled capacity percentage * 100
162
* (if absent assume 10%) */
163
},
164
/* OV5 */ {
165
sizeof(struct opt_vec5) - 2, /* length (n-2) */
166
0, /* don't ignore */
167
OV5_LPAR | OV5_SPLPAR | OV5_LP | OV5_MSI,
168
0,
169
0, /* Cooperative Memory Over-commitment */
170
0, /* Associativity Information Option */
171
0, /* Binary Option Controls */
172
0, /* Reserved */
173
0, /* Reserved */
174
OV5_MAX_CPUS(0),
175
OV5_MAX_CPUS(1), /* 10 */
176
OV5_MAX_CPUS(2),
177
OV5_MAX_CPUS(3),
178
OV5_LOPAPR_LEVEL(0),
179
OV5_LOPAPR_LEVEL(1),
180
0, /* Reserved */
181
0, /* Reserved */
182
0, /* Platform Facilities */
183
0, /* Reserved */
184
0, /* Reserved */
185
0, /* Reserved */ /* 20 */
186
OV5_NO_SUBPROCS,
187
0, /* DRMEM_V2 */
188
OV5_INTC_XICS,
189
OV5_MMU_HPT,
190
0,
191
0
192
}
193
};
194
195
int
196
ppc64_cas(void)
197
{
198
phandle_t pkg;
199
ihandle_t inst;
200
cell_t err = 0;
201
uint8_t buf[16], idx, val;
202
int i, len, rc, radix_mmu;
203
const char *var;
204
char *ov5;
205
206
pkg = OF_finddevice("/chosen");
207
if (pkg == -1) {
208
printf("cas: couldn't find /chosen\n");
209
return (-1);
210
}
211
212
len = OF_getprop(pkg, "ibm,arch-vec-5-platform-support", buf,
213
sizeof(buf));
214
if (len == -1)
215
/* CAS not supported */
216
return (0);
217
218
radix_mmu = 0;
219
ov5 = ibm_arch_vec.vec5.data;
220
for (i = 0; i < len; i += 2) {
221
idx = buf[i];
222
val = buf[i + 1];
223
DPRINTF("idx 0x%02x val 0x%02x\n", idx, val);
224
225
switch (idx) {
226
case OV5_MMU_INDEX:
227
/*
228
* Note that testing for OV5_MMU_RADIX/OV5_MMU_EITHER
229
* also covers OV5_MMU_DYNAMIC.
230
*/
231
if ((val & OV5_MMU_RADIX) || (val & OV5_MMU_EITHER))
232
radix_mmu = 1;
233
break;
234
235
case OV5_RADIX_EXT_INDEX:
236
if (val & OV5_RADIX_GTSE)
237
ov5[idx] = OV5_RADIX_GTSE;
238
break;
239
240
case OV5_HPT_EXT_INDEX:
241
default:
242
break;
243
}
244
}
245
246
if (!radix_mmu)
247
/*
248
* If radix is not supported, set radix_mmu to 0 to avoid
249
* the kernel trying to use it and panic.
250
*/
251
setenv("radix_mmu", "0", 1);
252
else if ((var = getenv("radix_mmu")) != NULL && var[0] == '0')
253
radix_mmu = 0;
254
else
255
ov5[OV5_MMU_INDEX] = OV5_MMU_RADIX;
256
257
inst = OF_open("/");
258
if (inst == -1) {
259
printf("cas: failed to open / node\n");
260
return (-1);
261
}
262
263
DPRINTF("MMU 0x%02x RADIX_EXT 0x%02x\n",
264
ov5[OV5_MMU_INDEX], ov5[OV5_RADIX_EXT_INDEX]);
265
rc = OF_call_method("ibm,client-architecture-support",
266
inst, 1, 1, &ibm_arch_vec, &err);
267
if (rc != 0 || err) {
268
printf("cas: CAS method returned an error: rc %d err %jd\n",
269
rc, (intmax_t)err);
270
rc = -1;
271
}
272
273
OF_close(inst);
274
printf("cas: selected %s MMU\n", radix_mmu ? "radix" : "hash");
275
return (rc);
276
}
277
278