~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/skiboot/hdata/cpu-common.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2013-2014 IBM Corp.
 
2
 *
 
3
 * Licensed under the Apache License, Version 2.0 (the "License");
 
4
 * you may not use this file except in compliance with the License.
 
5
 * You may obtain a copy of the License at
 
6
 *
 
7
 *      http://www.apache.org/licenses/LICENSE-2.0
 
8
 *
 
9
 * Unless required by applicable law or agreed to in writing, software
 
10
 * distributed under the License is distributed on an "AS IS" BASIS,
 
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 
12
 * implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
#include <skiboot.h>
 
17
#include "spira.h"
 
18
#include <cpu.h>
 
19
#include <ccan/str/str.h>
 
20
#include <device.h>
 
21
 
 
22
#include "hdata.h"
 
23
 
 
24
struct dt_node * add_core_common(struct dt_node *cpus,
 
25
                                 const struct sppcia_cpu_cache *cache,
 
26
                                 const struct sppaca_cpu_timebase *tb,
 
27
                                 uint32_t int_server, bool okay)
 
28
{
 
29
        const char *name;
 
30
        struct dt_node *cpu;
 
31
        uint32_t version;
 
32
        uint64_t freq;
 
33
        const uint8_t pa_features[] = {
 
34
                6, 0, 0xf6, 0x3f, 0xc7, 0x00, 0x80, 0xc0 };
 
35
 
 
36
        prlog(PR_INFO, "    Cache: I=%u D=%u/%u/%u/%u\n",
 
37
              be32_to_cpu(cache->icache_size_kb),
 
38
              be32_to_cpu(cache->l1_dcache_size_kb),
 
39
              be32_to_cpu(cache->l2_dcache_size_kb),
 
40
              be32_to_cpu(cache->l3_dcache_size_kb),
 
41
              be32_to_cpu(cache->l35_dcache_size_kb));
 
42
 
 
43
        /* Use the boot CPU PVR to make up a CPU name in the device-tree
 
44
         * since the HDAT doesn't seem to tell....
 
45
         */
 
46
        version = mfspr(SPR_PVR);
 
47
        switch(PVR_TYPE(version)) {
 
48
        case PVR_TYPE_P7:
 
49
                name = "PowerPC,POWER7";
 
50
                break;
 
51
        case PVR_TYPE_P7P:
 
52
                name = "PowerPC,POWER7+";
 
53
                break;
 
54
        case PVR_TYPE_P8E:
 
55
        case PVR_TYPE_P8:
 
56
        case PVR_TYPE_P8NVL:
 
57
                name = "PowerPC,POWER8";
 
58
                break;
 
59
        case PVR_TYPE_P9:
 
60
                name = "PowerPC,POWER9";
 
61
                break;
 
62
        default:
 
63
                name = "PowerPC,Unknown";
 
64
        }
 
65
 
 
66
        cpu = dt_new_addr(cpus, name, int_server);
 
67
        assert(cpu);
 
68
        dt_add_property_string(cpu, "device_type", "cpu");
 
69
        dt_add_property_string(cpu, "status", okay ? "okay" : "bad");
 
70
        dt_add_property_cells(cpu, "reg", int_server);
 
71
        dt_add_property_cells(cpu, "cpu-version", version);
 
72
        dt_add_property(cpu, "64-bit", NULL, 0);
 
73
        dt_add_property(cpu, "32-64-bridge", NULL, 0);
 
74
        dt_add_property(cpu, "graphics", NULL, 0);
 
75
        dt_add_property(cpu, "general-purpose", NULL, 0);
 
76
        dt_add_property_cells(cpu, "ibm,processor-segment-sizes",
 
77
                              0x1c, 0x28, 0xffffffff, 0xffffffff);
 
78
        dt_add_property_cells(cpu, "ibm,processor-page-sizes",
 
79
                              0xc, 0x10, 0x18, 0x22);
 
80
 
 
81
        /* Page size encodings appear to be the same for P7 and P8 */
 
82
        dt_add_property_cells(cpu, "ibm,segment-page-sizes",
 
83
                0x0c, 0x000, 3, 0x0c, 0x0000,  /*  4K seg  4k pages */
 
84
                                0x10, 0x0007,  /*  4K seg 64k pages */
 
85
                                0x18, 0x0038,  /*  4K seg 16M pages */
 
86
                0x10, 0x110, 2, 0x10, 0x0001,  /* 64K seg 64k pages */
 
87
                                0x18, 0x0008,  /* 64K seg 16M pages */
 
88
                0x18, 0x100, 1, 0x18, 0x0000,  /* 16M seg 16M pages */
 
89
                0x22, 0x120, 1, 0x22, 0x0003); /* 16G seg 16G pages */
 
90
                              
 
91
        dt_add_property(cpu, "ibm,pa-features",
 
92
                        pa_features, sizeof(pa_features));
 
93
        dt_add_property_cells(cpu, "ibm,slb-size", 0x20);
 
94
 
 
95
        dt_add_property_cells(cpu, "ibm,vmx", 0x2);
 
96
        dt_add_property_cells(cpu, "ibm,dfp", 0x2);
 
97
        dt_add_property_cells(cpu, "ibm,purr", 0x1);
 
98
        dt_add_property_cells(cpu, "ibm,spurr", 0x1);
 
99
 
 
100
        /*
 
101
         * Do not create "clock-frequency" if the frequency doesn't
 
102
         * fit in a single cell
 
103
         */
 
104
        freq = ((uint64_t)be32_to_cpu(tb->actual_clock_speed)) * 1000000ul;
 
105
        if (freq <= 0xfffffffful)
 
106
                dt_add_property_cells(cpu, "clock-frequency", freq);
 
107
        dt_add_property_cells(cpu, "ibm,extended-clock-frequency",
 
108
                              hi32(freq), lo32(freq));
 
109
 
 
110
        /* FIXME: Hardcoding is bad. */
 
111
        dt_add_property_cells(cpu, "timebase-frequency", 512000000);
 
112
        dt_add_property_cells(cpu, "ibm,extended-timebase-frequency",
 
113
                              0, 512000000);
 
114
 
 
115
        dt_add_property_cells(cpu, "reservation-granule-size",
 
116
                              be32_to_cpu(cache->reservation_size));
 
117
 
 
118
        dt_add_property_cells(cpu, "d-tlb-size",
 
119
                              be32_to_cpu(cache->dtlb_entries));
 
120
        dt_add_property_cells(cpu, "i-tlb-size",
 
121
                              be32_to_cpu(cache->itlb_entries));
 
122
        /* Assume unified TLB */
 
123
        dt_add_property_cells(cpu, "tlb-size",
 
124
                              be32_to_cpu(cache->dtlb_entries));
 
125
        dt_add_property_cells(cpu, "d-tlb-sets",
 
126
                              be32_to_cpu(cache->dtlb_assoc_sets));
 
127
        dt_add_property_cells(cpu, "i-tlb-sets",
 
128
                              be32_to_cpu(cache->itlb_assoc_sets));
 
129
        dt_add_property_cells(cpu, "tlb-sets",
 
130
                              be32_to_cpu(cache->dtlb_assoc_sets));
 
131
 
 
132
        dt_add_property_cells(cpu, "d-cache-block-size",
 
133
                              be32_to_cpu(cache->dcache_block_size));
 
134
        dt_add_property_cells(cpu, "i-cache-block-size",
 
135
                              be32_to_cpu(cache->icache_block_size));
 
136
        dt_add_property_cells(cpu, "d-cache-size",
 
137
                              be32_to_cpu(cache->l1_dcache_size_kb)*1024);
 
138
        dt_add_property_cells(cpu, "i-cache-size",
 
139
                              be32_to_cpu(cache->icache_size_kb)*1024);
 
140
        dt_add_property_cells(cpu, "i-cache-sets",
 
141
                              be32_to_cpu(cache->icache_assoc_sets));
 
142
        dt_add_property_cells(cpu, "d-cache-sets",
 
143
                              be32_to_cpu(cache->dcache_assoc_sets));
 
144
 
 
145
        if (cache->icache_line_size != cache->icache_block_size)
 
146
                dt_add_property_cells(cpu, "i-cache-line-size",
 
147
                                      be32_to_cpu(cache->icache_line_size));
 
148
        if (cache->l1_dcache_line_size != cache->dcache_block_size)
 
149
                dt_add_property_cells(cpu, "d-cache-line-size",
 
150
                                      be32_to_cpu(cache->l1_dcache_line_size));
 
151
        return cpu;
 
152
}
 
153
 
 
154
void add_core_attr(struct dt_node *cpu, uint32_t attr)
 
155
{
 
156
        if (attr & CPU_ATTR_UNIFIED_PL1)
 
157
                dt_add_property(cpu, "cache-unified", NULL, 0);
 
158
        if (attr & CPU_ATTR_SPLIT_TLB)
 
159
                dt_add_property(cpu, "tlb-split", NULL, 0);
 
160
        if (attr & CPU_ATTR_TLBIA)
 
161
                dt_add_property(cpu, "tlbia", NULL, 0);
 
162
        if (attr & CPU_ATTR_PERF_MONITOR)
 
163
                dt_add_property_cells(cpu, "performance-monitor", 0, 1);
 
164
        if (attr & CPU_ATTR_EXTERN_CONT)
 
165
                dt_add_property(cpu, "external-control", NULL, 0);
 
166
}
 
167
 
 
168
static struct dt_node *create_cache_node(struct dt_node *cpus,
 
169
                                         const struct sppcia_cpu_cache *cache,
 
170
                                         const char *name, uint32_t unit_addr,
 
171
                                         int okay)
 
172
{
 
173
        struct dt_node *node;
 
174
 
 
175
        node = dt_new_addr(cpus, name, unit_addr);
 
176
        assert(node);
 
177
 
 
178
        dt_add_property_string(node, "device_type", "cache");
 
179
        dt_add_property_cells(node, "reg", unit_addr);
 
180
        dt_add_property_string(node, "status", okay ? "okay" : "bad");
 
181
        dt_add_property(node, "cache-unified", NULL, 0);
 
182
 
 
183
        /* Assume cache associavitity sets is same for L2, L3 and L3.5 */
 
184
        dt_add_property_cells(node, "d-cache-sets",
 
185
                              be32_to_cpu(cache->l2_cache_assoc_sets));
 
186
        dt_add_property_cells(node, "i-cache-sets",
 
187
                              be32_to_cpu(cache->l2_cache_assoc_sets));
 
188
 
 
189
        return node;
 
190
}
 
191
 
 
192
static struct dt_node *l35_cache_node(struct dt_node *cpus,
 
193
                                      const struct sppcia_cpu_cache *cache,
 
194
                                      uint32_t unit_addr, int okay)
 
195
{
 
196
        struct dt_node *node;
 
197
 
 
198
        node = create_cache_node(cpus, cache, "l35-cache", unit_addr, okay);
 
199
 
 
200
        dt_add_property_cells(node, "d-cache-size",
 
201
                              be32_to_cpu(cache->l35_dcache_size_kb) * 1024);
 
202
        dt_add_property_cells(node, "i-cache-size",
 
203
                              be32_to_cpu(cache->l35_dcache_size_kb) * 1024);
 
204
 
 
205
        if (cache->icache_line_size != cache->icache_block_size)
 
206
                dt_add_property_cells(node, "i-cache-line-size",
 
207
                                      be32_to_cpu(cache->icache_line_size));
 
208
        if (cache->l35_cache_line_size != cache->dcache_block_size)
 
209
                dt_add_property_cells(node, "d-cache-line-size",
 
210
                                      be32_to_cpu(cache->l35_cache_line_size));
 
211
 
 
212
        return node;
 
213
}
 
214
 
 
215
static struct dt_node *l3_cache_node(struct dt_node *cpus,
 
216
                                     const struct sppcia_cpu_cache *cache,
 
217
                                     uint32_t unit_addr, int okay)
 
218
{
 
219
        struct dt_node *node;
 
220
 
 
221
        node = create_cache_node(cpus, cache, "l3-cache", unit_addr, okay);
 
222
 
 
223
        dt_add_property_cells(node, "d-cache-size",
 
224
                              be32_to_cpu(cache->l3_dcache_size_kb) * 1024);
 
225
        dt_add_property_cells(node, "i-cache-size",
 
226
                              be32_to_cpu(cache->l3_dcache_size_kb) * 1024);
 
227
 
 
228
        if (cache->icache_line_size != cache->icache_block_size)
 
229
                dt_add_property_cells(node, "i-cache-line-size",
 
230
                                      be32_to_cpu(cache->icache_line_size));
 
231
        if (cache->l3_line_size != cache->dcache_block_size)
 
232
                dt_add_property_cells(node, "d-cache-line-size",
 
233
                                      be32_to_cpu(cache->l3_line_size));
 
234
 
 
235
        return node;
 
236
}
 
237
 
 
238
static struct dt_node *l2_cache_node(struct dt_node *cpus,
 
239
                                     const struct sppcia_cpu_cache *cache,
 
240
                                     uint32_t unit_addr, int okay)
 
241
{
 
242
        struct dt_node *node;
 
243
 
 
244
        node = create_cache_node(cpus, cache, "l2-cache", unit_addr, okay);
 
245
 
 
246
        dt_add_property_cells(node, "d-cache-size",
 
247
                              be32_to_cpu(cache->l2_dcache_size_kb) * 1024);
 
248
        dt_add_property_cells(node, "i-cache-size",
 
249
                              be32_to_cpu(cache->l2_dcache_size_kb) * 1024);
 
250
 
 
251
        if (cache->icache_line_size != cache->icache_block_size)
 
252
                dt_add_property_cells(node, "i-cache-line-size",
 
253
                                      be32_to_cpu(cache->icache_line_size));
 
254
        if (cache->l2_line_size != cache->dcache_block_size)
 
255
                dt_add_property_cells(node, "d-cache-line-size",
 
256
                                      be32_to_cpu(cache->l2_line_size));
 
257
 
 
258
        return node;
 
259
}
 
260
 
 
261
uint32_t add_core_cache_info(struct dt_node *cpus,
 
262
                             const struct sppcia_cpu_cache *cache,
 
263
                             uint32_t int_server, int okay)
 
264
{
 
265
        struct dt_node *l2_node, *l3_node, *l35_node;
 
266
        uint32_t unit_addr;
 
267
 
 
268
        /* Use Processor Interrupt Line to genarate cache unit address */
 
269
        unit_addr = 0x20 << 24 | int_server;
 
270
        l2_node = l2_cache_node(cpus, cache, unit_addr, okay);
 
271
 
 
272
        unit_addr = 0x30 << 24 | int_server;
 
273
        l3_node = l3_cache_node(cpus, cache, unit_addr, okay);
 
274
        /* Represents the next level of cache in the memory hierarchy */
 
275
        dt_add_property_cells(l2_node, "l2-cache", l3_node->phandle);
 
276
 
 
277
        if (be32_to_cpu(cache->l35_dcache_size_kb)) {
 
278
                unit_addr = 0x35 << 24 | int_server;
 
279
                l35_node = l35_cache_node(cpus, cache, unit_addr, okay);
 
280
                dt_add_property_cells(l3_node, "l2-cache", l35_node->phandle);
 
281
        }
 
282
 
 
283
        return l2_node->phandle;
 
284
}