1 /*
2 * psr.c: Platform Shared Resource related service for guest.
3 *
4 * Copyright (c) 2014, Intel Corporation
5 * Author: Dongxiao Xu <dongxiao.xu@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 */
16 #include <xen/cpu.h>
17 #include <xen/err.h>
18 #include <xen/init.h>
19 #include <xen/sched.h>
20 #include <asm/psr.h>
21
22 /*
23 * Terminology:
24 * - CAT Cache Allocation Technology
25 * - CBM Capacity BitMasks
26 * - CDP Code and Data Prioritization
27 * - CMT Cache Monitoring Technology
28 * - COS/CLOS Class of Service. Also mean COS registers.
29 * - COS_MAX Max number of COS for the feature (minus 1)
30 * - MSRs Machine Specific Registers
31 * - PSR Intel Platform Shared Resource
32 */
33
34 #define PSR_CMT (1u << 0)
35 #define PSR_CAT (1u << 1)
36 #define PSR_CDP (1u << 2)
37
38 #define CAT_CBM_LEN_MASK 0x1f
39 #define CAT_COS_MAX_MASK 0xffff
40
41 /*
42 * Per SDM chapter 'Cache Allocation Technology: Cache Mask Configuration',
43 * the MSRs ranging from 0C90H through 0D0FH (inclusive), enables support for
44 * up to 128 L3 CAT Classes of Service. The COS_ID=[0,127].
45 *
46 * The MSRs ranging from 0D10H through 0D4FH (inclusive), enables support for
47 * up to 64 L2 CAT COS. The COS_ID=[0,63].
48 *
49 * So, the maximum COS register count of one feature is 128.
50 */
51 #define MAX_COS_REG_CNT 128
52
53 #define ASSOC_REG_SHIFT 32
54
55 /*
56 * Every PSR feature uses some COS registers for each COS ID, e.g. CDP uses 2
57 * COS registers (DATA and CODE) for one COS ID, but CAT uses 1 COS register.
58 * We use below macro as the max number of COS registers used by all features.
59 * So far, it is 2 which means CDP's COS registers number.
60 */
61 #define MAX_COS_NUM 2
62
63 enum psr_feat_type {
64 FEAT_TYPE_L3_CAT,
65 FEAT_TYPE_L3_CDP,
66 FEAT_TYPE_L2_CAT,
67 FEAT_TYPE_NUM,
68 FEAT_TYPE_UNKNOWN,
69 };
70
71 /*
72 * This structure represents one feature.
73 * cos_max - The max COS registers number got through CPUID.
74 * cbm_len - The length of CBM got through CPUID.
75 * cos_reg_val - Array to store the values of COS registers. One entry stores
76 * the value of one COS register.
77 * For L3 CAT and L2 CAT, one entry corresponds to one COS_ID.
78 * For CDP, two entries correspond to one COS_ID. E.g.
79 * COS_ID=0 corresponds to cos_reg_val[0] (Data) and
80 * cos_reg_val[1] (Code).
81 */
82 struct feat_node {
83 /* cos_max and cbm_len are common values for all features so far. */
84 unsigned int cos_max;
85 unsigned int cbm_len;
86 uint32_t cos_reg_val[MAX_COS_REG_CNT];
87 };
88
89 /*
90 * This structure defines feature specific values, e.g. cos_num.
91 *
92 * Array 'feat_props' is defined to save every feature's properties. We use
93 * 'enum psr_feat_type' as index.
94 */
95 static const struct feat_props {
96 /*
97 * cos_num - COS registers number that feature uses for one COS ID.
98 * It is defined in SDM.
99 */
100 unsigned int cos_num;
101
102 /*
103 * An array to save all 'enum cbm_type' values of the feature. It is
104 * used with cos_num together to get/write a feature's COS registers
105 * values one by one.
106 */
107 enum cbm_type type[MAX_COS_NUM];
108
109 /*
110 * alt_type is 'alternative type'. When this 'alt_type' is input, the
111 * feature does some special operations.
112 */
113 enum cbm_type alt_type;
114
115 /* get_feat_info is used to return feature HW info through sysctl. */
116 bool (*get_feat_info)(const struct feat_node *feat,
117 uint32_t data[], unsigned int array_len);
118
119 /* write_msr is used to write out feature MSR register. */
120 void (*write_msr)(unsigned int cos, uint32_t val, enum cbm_type type);
121 } *feat_props[FEAT_TYPE_NUM];
122
123 /*
124 * PSR features are managed per socket. Below structure defines the members
125 * used to manage these features.
126 * feat_init - Indicate if features on a socket have been initialized.
127 * features - A feature node array used to manage all features enabled.
128 * ref_lock - A lock to protect cos_ref.
129 * cos_ref - A reference count array to record how many domains are using the
130 * COS ID. Every entry of cos_ref corresponds to one COS ID.
131 * dom_set - A bitmap to indicate which domain's cos id has been set.
132 */
133 struct psr_socket_info {
134 bool feat_init;
135 /* Feature array's index is 'enum psr_feat_type' which is same as 'props' */
136 struct feat_node *features[FEAT_TYPE_NUM];
137 spinlock_t ref_lock;
138 unsigned int cos_ref[MAX_COS_REG_CNT];
139 /* Every bit corresponds to a domain. Index is domain_id. */
140 DECLARE_BITMAP(dom_set, DOMID_IDLE + 1);
141 };
142
143 struct psr_assoc {
144 uint64_t val;
145 uint64_t cos_mask;
146 };
147
148 struct psr_cmt *__read_mostly psr_cmt;
149
150 static struct psr_socket_info *__read_mostly socket_info;
151
152 static unsigned int opt_psr;
153 static unsigned int __initdata opt_rmid_max = 255;
154 static unsigned int __read_mostly opt_cos_max = MAX_COS_REG_CNT;
155 static uint64_t rmid_mask;
156 static DEFINE_PER_CPU(struct psr_assoc, psr_assoc);
157
158 /*
159 * Declare global feature node for every feature to facilitate the feature
160 * array creation. It is used to transiently store a spare node.
161 */
162 static struct feat_node *feat_l3;
163 static struct feat_node *feat_l2_cat;
164
165 /* Common functions */
166 #define cat_default_val(len) (0xffffffff >> (32 - (len)))
167
168 /*
169 * get_cdp_data - get DATA COS register value from input COS ID.
170 * @feat: the feature node.
171 * @cos: the COS ID.
172 */
173 #define get_cdp_data(feat, cos) \
174 ((feat)->cos_reg_val[(cos) * 2])
175
176 /*
177 * get_cdp_code - get CODE COS register value from input COS ID.
178 * @feat: the feature node.
179 * @cos: the COS ID.
180 */
181 #define get_cdp_code(feat, cos) \
182 ((feat)->cos_reg_val[(cos) * 2 + 1])
183
184 /*
185 * Use this function to check if any allocation feature has been enabled
186 * in cmdline.
187 */
psr_alloc_feat_enabled(void)188 static bool psr_alloc_feat_enabled(void)
189 {
190 return !!socket_info;
191 }
192
free_socket_resources(unsigned int socket)193 static void free_socket_resources(unsigned int socket)
194 {
195 unsigned int i;
196 struct psr_socket_info *info = socket_info + socket;
197
198 ASSERT(socket_info);
199
200 /*
201 * Free resources of features. The global feature object, e.g. feat_l3,
202 * may not be freed here if it is not added into array. It is simply being
203 * kept until the next CPU online attempt.
204 */
205 for ( i = 0; i < ARRAY_SIZE(info->features); i++ )
206 {
207 xfree(info->features[i]);
208 info->features[i] = NULL;
209 }
210
211 info->feat_init = false;
212
213 memset(info->cos_ref, 0, MAX_COS_REG_CNT * sizeof(unsigned int));
214
215 bitmap_zero(info->dom_set, DOMID_IDLE + 1);
216 }
217
psr_cbm_type_to_feat_type(enum cbm_type type)218 static enum psr_feat_type psr_cbm_type_to_feat_type(enum cbm_type type)
219 {
220 enum psr_feat_type feat_type = FEAT_TYPE_UNKNOWN;
221
222 switch ( type )
223 {
224 case PSR_CBM_TYPE_L3:
225 feat_type = FEAT_TYPE_L3_CAT;
226
227 /*
228 * If type is L3 CAT but we cannot find it in feat_props array,
229 * try CDP.
230 */
231 if ( !feat_props[feat_type] )
232 feat_type = FEAT_TYPE_L3_CDP;
233
234 break;
235
236 case PSR_CBM_TYPE_L3_DATA:
237 case PSR_CBM_TYPE_L3_CODE:
238 feat_type = FEAT_TYPE_L3_CDP;
239 break;
240
241 case PSR_CBM_TYPE_L2:
242 feat_type = FEAT_TYPE_L2_CAT;
243 break;
244
245 default:
246 ASSERT_UNREACHABLE();
247 }
248
249 return feat_type;
250 }
251
psr_check_cbm(unsigned int cbm_len,unsigned long cbm)252 static bool psr_check_cbm(unsigned int cbm_len, unsigned long cbm)
253 {
254 unsigned int first_bit, zero_bit;
255
256 /* Set bits should only in the range of [0, cbm_len]. */
257 if ( cbm & (~0ul << cbm_len) )
258 return false;
259
260 /* At least one bit need to be set. */
261 if ( cbm == 0 )
262 return false;
263
264 first_bit = find_first_bit(&cbm, cbm_len);
265 zero_bit = find_next_zero_bit(&cbm, cbm_len, first_bit);
266
267 /* Set bits should be contiguous. */
268 if ( zero_bit < cbm_len &&
269 find_next_bit(&cbm, cbm_len, zero_bit) < cbm_len )
270 return false;
271
272 return true;
273 }
274
275 /* CAT common functions implementation. */
cat_init_feature(const struct cpuid_leaf * regs,struct feat_node * feat,struct psr_socket_info * info,enum psr_feat_type type)276 static int cat_init_feature(const struct cpuid_leaf *regs,
277 struct feat_node *feat,
278 struct psr_socket_info *info,
279 enum psr_feat_type type)
280 {
281 const char *const cat_feat_name[FEAT_TYPE_NUM] = {
282 [FEAT_TYPE_L3_CAT] = "L3 CAT",
283 [FEAT_TYPE_L3_CDP] = "L3 CDP",
284 [FEAT_TYPE_L2_CAT] = "L2 CAT",
285 };
286
287 /* No valid value so do not enable feature. */
288 if ( !regs->a || !regs->d )
289 return -ENOENT;
290
291 feat->cbm_len = (regs->a & CAT_CBM_LEN_MASK) + 1;
292 feat->cos_max = min(opt_cos_max, regs->d & CAT_COS_MAX_MASK);
293
294 switch ( type )
295 {
296 case FEAT_TYPE_L3_CAT:
297 case FEAT_TYPE_L2_CAT:
298 if ( feat->cos_max < 1 )
299 return -ENOENT;
300
301 /* We reserve cos=0 as default cbm (all bits within cbm_len are 1). */
302 feat->cos_reg_val[0] = cat_default_val(feat->cbm_len);
303
304 wrmsrl((type == FEAT_TYPE_L3_CAT ?
305 MSR_IA32_PSR_L3_MASK(0) :
306 MSR_IA32_PSR_L2_MASK(0)),
307 cat_default_val(feat->cbm_len));
308
309 break;
310
311 case FEAT_TYPE_L3_CDP:
312 {
313 uint64_t val;
314
315 if ( feat->cos_max < 3 )
316 return -ENOENT;
317
318 /* Cut half of cos_max when CDP is enabled. */
319 feat->cos_max = (feat->cos_max - 1) >> 1;
320
321 /* We reserve cos=0 as default cbm (all bits within cbm_len are 1). */
322 get_cdp_code(feat, 0) = cat_default_val(feat->cbm_len);
323 get_cdp_data(feat, 0) = cat_default_val(feat->cbm_len);
324
325 wrmsrl(MSR_IA32_PSR_L3_MASK(0), cat_default_val(feat->cbm_len));
326 wrmsrl(MSR_IA32_PSR_L3_MASK(1), cat_default_val(feat->cbm_len));
327 rdmsrl(MSR_IA32_PSR_L3_QOS_CFG, val);
328 wrmsrl(MSR_IA32_PSR_L3_QOS_CFG,
329 val | (1ull << PSR_L3_QOS_CDP_ENABLE_BIT));
330
331 break;
332 }
333
334 default:
335 return -ENOENT;
336 }
337
338 /* Add this feature into array. */
339 info->features[type] = feat;
340
341 if ( !opt_cpu_info )
342 return 0;
343
344 printk(XENLOG_INFO "%s: enabled on socket %u, cos_max:%u, cbm_len:%u\n",
345 cat_feat_name[type], cpu_to_socket(smp_processor_id()),
346 feat->cos_max, feat->cbm_len);
347
348 return 0;
349 }
350
cat_get_feat_info(const struct feat_node * feat,uint32_t data[],unsigned int array_len)351 static bool cat_get_feat_info(const struct feat_node *feat,
352 uint32_t data[], unsigned int array_len)
353 {
354 if ( array_len != PSR_INFO_ARRAY_SIZE )
355 return false;
356
357 data[PSR_INFO_IDX_COS_MAX] = feat->cos_max;
358 data[PSR_INFO_IDX_CAT_CBM_LEN] = feat->cbm_len;
359 data[PSR_INFO_IDX_CAT_FLAG] = 0;
360
361 return true;
362 }
363
364 /* L3 CAT props */
l3_cat_write_msr(unsigned int cos,uint32_t val,enum cbm_type type)365 static void l3_cat_write_msr(unsigned int cos, uint32_t val, enum cbm_type type)
366 {
367 wrmsrl(MSR_IA32_PSR_L3_MASK(cos), val);
368 }
369
370 static const struct feat_props l3_cat_props = {
371 .cos_num = 1,
372 .type[0] = PSR_CBM_TYPE_L3,
373 .alt_type = PSR_CBM_TYPE_UNKNOWN,
374 .get_feat_info = cat_get_feat_info,
375 .write_msr = l3_cat_write_msr,
376 };
377
378 /* L3 CDP props */
l3_cdp_get_feat_info(const struct feat_node * feat,uint32_t data[],uint32_t array_len)379 static bool l3_cdp_get_feat_info(const struct feat_node *feat,
380 uint32_t data[], uint32_t array_len)
381 {
382 if ( !cat_get_feat_info(feat, data, array_len) )
383 return false;
384
385 data[PSR_INFO_IDX_CAT_FLAG] |= XEN_SYSCTL_PSR_CAT_L3_CDP;
386
387 return true;
388 }
389
l3_cdp_write_msr(unsigned int cos,uint32_t val,enum cbm_type type)390 static void l3_cdp_write_msr(unsigned int cos, uint32_t val, enum cbm_type type)
391 {
392 wrmsrl(((type == PSR_CBM_TYPE_L3_DATA) ?
393 MSR_IA32_PSR_L3_MASK_DATA(cos) :
394 MSR_IA32_PSR_L3_MASK_CODE(cos)),
395 val);
396 }
397
398 static const struct feat_props l3_cdp_props = {
399 .cos_num = 2,
400 .type[0] = PSR_CBM_TYPE_L3_DATA,
401 .type[1] = PSR_CBM_TYPE_L3_CODE,
402 .alt_type = PSR_CBM_TYPE_L3,
403 .get_feat_info = l3_cdp_get_feat_info,
404 .write_msr = l3_cdp_write_msr,
405 };
406
407 /* L2 CAT props */
l2_cat_write_msr(unsigned int cos,uint32_t val,enum cbm_type type)408 static void l2_cat_write_msr(unsigned int cos, uint32_t val, enum cbm_type type)
409 {
410 wrmsrl(MSR_IA32_PSR_L2_MASK(cos), val);
411 }
412
413 static const struct feat_props l2_cat_props = {
414 .cos_num = 1,
415 .type[0] = PSR_CBM_TYPE_L2,
416 .alt_type = PSR_CBM_TYPE_UNKNOWN,
417 .get_feat_info = cat_get_feat_info,
418 .write_msr = l2_cat_write_msr,
419 };
420
parse_psr_bool(const char * s,const char * delim,const char * ss,const char * feature,unsigned int mask)421 static bool __init parse_psr_bool(const char *s, const char *delim,
422 const char *ss, const char *feature,
423 unsigned int mask)
424 {
425 /* If cmdline is 'psr=', we need make sure delim != s */
426 if ( delim != s && !strncmp(s, feature, delim - s) )
427 {
428 if ( !*delim || *delim == ',' )
429 opt_psr |= mask;
430 else
431 {
432 int val_int = parse_bool(delim + 1, ss);
433
434 if ( val_int == 0 )
435 opt_psr &= ~mask;
436 else if ( val_int == 1 )
437 opt_psr |= mask;
438 else
439 return false;
440 }
441 return true;
442 }
443 return false;
444 }
445
parse_psr_param(const char * s)446 static int __init parse_psr_param(const char *s)
447 {
448 const char *ss, *val_delim;
449 const char *q;
450 int rc = 0;
451
452 do {
453 ss = strchr(s, ',');
454 if ( !ss )
455 ss = strchr(s, '\0');
456
457 val_delim = strchr(s, ':');
458 if ( !val_delim )
459 val_delim = strchr(s, '\0');
460
461 /* E.g. 'psr=cmt,rmid_max:200' */
462 if ( val_delim > ss )
463 val_delim = ss;
464
465 if ( *val_delim && !strncmp(s, "rmid_max", val_delim - s) )
466 {
467 opt_rmid_max = simple_strtoul(val_delim + 1, &q, 0);
468 if ( *q && *q != ',' )
469 rc = -EINVAL;
470 }
471 else if ( *val_delim && !strncmp(s, "cos_max", val_delim - s) )
472 {
473 opt_cos_max = simple_strtoul(val_delim + 1, &q, 0);
474 if ( *q && *q != ',' )
475 rc = -EINVAL;
476 }
477 else if ( !parse_psr_bool(s, val_delim, ss, "cmt", PSR_CMT) &&
478 !parse_psr_bool(s, val_delim, ss, "cat", PSR_CAT) &&
479 !parse_psr_bool(s, val_delim, ss, "cdp", PSR_CDP) )
480 rc = -EINVAL;
481
482 s = ss + 1;
483 } while ( *ss );
484
485 return rc;
486 }
487 custom_param("psr", parse_psr_param);
488
init_psr_cmt(unsigned int rmid_max)489 static void __init init_psr_cmt(unsigned int rmid_max)
490 {
491 unsigned int eax, ebx, ecx, edx;
492 unsigned int rmid;
493
494 if ( !boot_cpu_has(X86_FEATURE_PQM) )
495 return;
496
497 cpuid_count(0xf, 0, &eax, &ebx, &ecx, &edx);
498 if ( !edx )
499 return;
500
501 psr_cmt = xzalloc(struct psr_cmt);
502 if ( !psr_cmt )
503 return;
504
505 psr_cmt->features = edx;
506 psr_cmt->rmid_max = min(rmid_max, ebx);
507 rmid_mask = ~(~0ull << get_count_order(ebx));
508
509 if ( psr_cmt->features & PSR_RESOURCE_TYPE_L3 )
510 {
511 cpuid_count(0xf, 1, &eax, &ebx, &ecx, &edx);
512 psr_cmt->l3.upscaling_factor = ebx;
513 psr_cmt->l3.rmid_max = ecx;
514 psr_cmt->l3.features = edx;
515 }
516
517 psr_cmt->rmid_max = min(psr_cmt->rmid_max, psr_cmt->l3.rmid_max);
518 psr_cmt->rmid_to_dom = xmalloc_array(domid_t, psr_cmt->rmid_max + 1UL);
519 if ( !psr_cmt->rmid_to_dom )
520 {
521 xfree(psr_cmt);
522 psr_cmt = NULL;
523 return;
524 }
525
526 /*
527 * Once CMT is enabled each CPU will always require a RMID to associate
528 * with it. To reduce the waste of RMID, reserve RMID 0 for all CPUs that
529 * have no domain being monitored.
530 */
531 psr_cmt->rmid_to_dom[0] = DOMID_XEN;
532 for ( rmid = 1; rmid <= psr_cmt->rmid_max; rmid++ )
533 psr_cmt->rmid_to_dom[rmid] = DOMID_INVALID;
534
535 printk(XENLOG_INFO "Cache Monitoring Technology enabled\n");
536 }
537
538 /* Called with domain lock held, no psr specific lock needed */
psr_alloc_rmid(struct domain * d)539 int psr_alloc_rmid(struct domain *d)
540 {
541 unsigned int rmid;
542
543 ASSERT(psr_cmt_enabled());
544
545 if ( d->arch.psr_rmid > 0 )
546 return -EEXIST;
547
548 for ( rmid = 1; rmid <= psr_cmt->rmid_max; rmid++ )
549 {
550 if ( psr_cmt->rmid_to_dom[rmid] != DOMID_INVALID )
551 continue;
552
553 psr_cmt->rmid_to_dom[rmid] = d->domain_id;
554 break;
555 }
556
557 /* No RMID available, assign RMID=0 by default. */
558 if ( rmid > psr_cmt->rmid_max )
559 {
560 d->arch.psr_rmid = 0;
561 return -EOVERFLOW;
562 }
563
564 d->arch.psr_rmid = rmid;
565
566 return 0;
567 }
568
569 /* Called with domain lock held, no psr specific lock needed */
psr_free_rmid(struct domain * d)570 void psr_free_rmid(struct domain *d)
571 {
572 unsigned int rmid;
573
574 rmid = d->arch.psr_rmid;
575 /* We do not free system reserved "RMID=0". */
576 if ( rmid == 0 )
577 return;
578
579 psr_cmt->rmid_to_dom[rmid] = DOMID_INVALID;
580 d->arch.psr_rmid = 0;
581 }
582
get_max_cos_max(const struct psr_socket_info * info)583 static unsigned int get_max_cos_max(const struct psr_socket_info *info)
584 {
585 unsigned int cos_max = 0, i;
586
587 for ( i = 0; i < ARRAY_SIZE(info->features); i++ )
588 {
589 const struct feat_node *feat = info->features[i];
590
591 if ( feat )
592 cos_max = max(feat->cos_max, cos_max);
593 }
594
595 return cos_max;
596 }
597
psr_assoc_init(void)598 static void psr_assoc_init(void)
599 {
600 struct psr_assoc *psra = &this_cpu(psr_assoc);
601
602 if ( psr_alloc_feat_enabled() )
603 {
604 unsigned int socket = cpu_to_socket(smp_processor_id());
605 const struct psr_socket_info *info = socket_info + socket;
606 unsigned int cos_max = get_max_cos_max(info);
607
608 if ( info->feat_init )
609 psra->cos_mask = ((1ull << get_count_order(cos_max)) - 1) <<
610 ASSOC_REG_SHIFT;
611 }
612
613 if ( psr_cmt_enabled() || psra->cos_mask )
614 rdmsrl(MSR_IA32_PSR_ASSOC, psra->val);
615 }
616
psr_assoc_rmid(uint64_t * reg,unsigned int rmid)617 static inline void psr_assoc_rmid(uint64_t *reg, unsigned int rmid)
618 {
619 *reg = (*reg & ~rmid_mask) | (rmid & rmid_mask);
620 }
621
psr_assoc_cos(uint64_t reg,unsigned int cos,uint64_t cos_mask)622 static uint64_t psr_assoc_cos(uint64_t reg, unsigned int cos,
623 uint64_t cos_mask)
624 {
625 return (reg & ~cos_mask) |
626 (((uint64_t)cos << ASSOC_REG_SHIFT) & cos_mask);
627 }
628
psr_ctxt_switch_to(struct domain * d)629 void psr_ctxt_switch_to(struct domain *d)
630 {
631 struct psr_assoc *psra = &this_cpu(psr_assoc);
632 uint64_t reg = psra->val;
633
634 if ( psr_cmt_enabled() )
635 psr_assoc_rmid(®, d->arch.psr_rmid);
636
637 /*
638 * If the domain is not set in 'dom_set' bitmap, that means the domain's
639 * cos id is not valid. So, we have to use default value (0) to set ASSOC
640 * register. Furthermore, if domain's 'psr_cos_ids' is NULL, we need
641 * default value for it too (for case that the domain's psr_cos_ids is not
642 * successfully allocated).
643 */
644 if ( psra->cos_mask )
645 {
646 unsigned int socket = cpu_to_socket(smp_processor_id());
647 struct psr_socket_info *info = socket_info + socket;
648 unsigned int cos = 0;
649
650 if ( likely(test_bit(d->domain_id, info->dom_set)) &&
651 d->arch.psr_cos_ids )
652 cos = d->arch.psr_cos_ids[socket];
653
654 reg = psr_assoc_cos(reg, cos, psra->cos_mask);
655 }
656
657 if ( reg != psra->val )
658 {
659 wrmsrl(MSR_IA32_PSR_ASSOC, reg);
660 psra->val = reg;
661 }
662 }
663
get_socket_info(unsigned int socket)664 static struct psr_socket_info *get_socket_info(unsigned int socket)
665 {
666 if ( !socket_info )
667 return ERR_PTR(-ENODEV);
668
669 if ( socket >= nr_sockets )
670 return ERR_PTR(-ERANGE);
671
672 if ( !socket_info[socket].feat_init )
673 return ERR_PTR(-ENOENT);
674
675 return socket_info + socket;
676 }
677
psr_get_info(unsigned int socket,enum cbm_type type,uint32_t data[],unsigned int array_len)678 int psr_get_info(unsigned int socket, enum cbm_type type,
679 uint32_t data[], unsigned int array_len)
680 {
681 const struct psr_socket_info *info = get_socket_info(socket);
682 const struct feat_node *feat;
683 enum psr_feat_type feat_type;
684
685 ASSERT(data);
686
687 if ( IS_ERR(info) )
688 return PTR_ERR(info);
689
690 feat_type = psr_cbm_type_to_feat_type(type);
691 if ( feat_type >= ARRAY_SIZE(info->features) )
692 return -ENOENT;
693
694 feat = info->features[feat_type];
695 if ( !feat )
696 return -ENOENT;
697
698 if ( !feat_props[feat_type] )
699 {
700 ASSERT_UNREACHABLE();
701 return -ENOENT;
702 }
703
704 if ( feat_props[feat_type]->get_feat_info(feat, data, array_len) )
705 return 0;
706
707 return -EINVAL;
708 }
709
psr_get_val(struct domain * d,unsigned int socket,uint32_t * val,enum cbm_type type)710 int psr_get_val(struct domain *d, unsigned int socket,
711 uint32_t *val, enum cbm_type type)
712 {
713 const struct psr_socket_info *info = get_socket_info(socket);
714 const struct feat_node *feat;
715 enum psr_feat_type feat_type;
716 unsigned int cos, i;
717
718 ASSERT(val);
719
720 if ( IS_ERR(info) )
721 return PTR_ERR(info);
722
723 feat_type = psr_cbm_type_to_feat_type(type);
724 if ( feat_type >= ARRAY_SIZE(info->features) )
725 return -ENOENT;
726
727 feat = info->features[feat_type];
728 if ( !feat )
729 return -ENOENT;
730
731 if ( !feat_props[feat_type] )
732 {
733 ASSERT_UNREACHABLE();
734 return -ENOENT;
735 }
736
737 domain_lock(d);
738 if ( !test_and_set_bit(d->domain_id, socket_info[socket].dom_set) )
739 d->arch.psr_cos_ids[socket] = 0;
740
741 cos = d->arch.psr_cos_ids[socket];
742 domain_unlock(d);
743
744 /*
745 * If input cos exceeds current feature's cos_max, we should return its
746 * default value which is stored in cos 0. This case only happens
747 * when more than two features enabled concurrently and at least one
748 * features's cos_max is bigger than others. When a domain's working cos
749 * id is bigger than some features' cos_max, HW automatically works as
750 * default value for those features which cos_max is smaller.
751 */
752 if ( cos > feat->cos_max )
753 cos = 0;
754
755 for ( i = 0; i < feat_props[feat_type]->cos_num; i++ )
756 {
757 if ( type == feat_props[feat_type]->type[i] )
758 {
759 *val = feat->cos_reg_val[cos * feat_props[feat_type]->cos_num + i];
760 return 0;
761 }
762 }
763
764 return -EINVAL;
765 }
766
767 /* Set value functions */
get_cos_num(void)768 static unsigned int get_cos_num(void)
769 {
770 unsigned int num = 0, i;
771
772 /* Get all features total amount. */
773 for ( i = 0; i < ARRAY_SIZE(feat_props); i++ )
774 if ( feat_props[i] )
775 num += feat_props[i]->cos_num;
776
777 return num;
778 }
779
gather_val_array(uint32_t val[],unsigned int array_len,const struct psr_socket_info * info,unsigned int old_cos)780 static int gather_val_array(uint32_t val[],
781 unsigned int array_len,
782 const struct psr_socket_info *info,
783 unsigned int old_cos)
784 {
785 unsigned int i;
786
787 if ( !val )
788 return -EINVAL;
789
790 /* Get all features current values according to old_cos. */
791 for ( i = 0; i < ARRAY_SIZE(info->features); i++ )
792 {
793 unsigned int cos = old_cos, j;
794 const struct feat_node *feat = info->features[i];
795 const struct feat_props *props = feat_props[i];
796
797 if ( !feat )
798 continue;
799
800 if ( !props )
801 {
802 ASSERT_UNREACHABLE();
803 return -ENOENT;
804 }
805
806 if ( array_len < props->cos_num )
807 return -ENOSPC;
808
809 /*
810 * If old_cos exceeds current feature's cos_max, we should get
811 * default value. So assign cos to 0 which stores default value.
812 */
813 if ( cos > feat->cos_max )
814 cos = 0;
815
816 /* Value getting order is same as feature array. */
817 for ( j = 0; j < props->cos_num; j++ )
818 val[j] = feat->cos_reg_val[cos * props->cos_num + j];
819
820 array_len -= props->cos_num;
821 val += props->cos_num;
822 }
823
824 return 0;
825 }
826
skip_prior_features(unsigned int * array_len,enum psr_feat_type feat_type)827 static int skip_prior_features(unsigned int *array_len,
828 enum psr_feat_type feat_type)
829 {
830 unsigned int i, skip_len = 0;
831
832 for ( i = 0; i < feat_type; i++ )
833 {
834 const struct feat_props *props = feat_props[i];
835
836 if ( !props )
837 continue;
838
839 if ( *array_len <= props->cos_num )
840 return -ENOSPC;
841
842 *array_len -= props->cos_num;
843 skip_len += props->cos_num;
844 }
845
846 return skip_len;
847 }
848
insert_val_into_array(uint32_t val[],unsigned int array_len,const struct psr_socket_info * info,enum psr_feat_type feat_type,enum cbm_type type,uint32_t new_val)849 static int insert_val_into_array(uint32_t val[],
850 unsigned int array_len,
851 const struct psr_socket_info *info,
852 enum psr_feat_type feat_type,
853 enum cbm_type type,
854 uint32_t new_val)
855 {
856 const struct feat_node *feat;
857 const struct feat_props *props;
858 unsigned int i;
859 int ret;
860
861 ASSERT(feat_type < FEAT_TYPE_NUM);
862
863 ret = skip_prior_features(&array_len, feat_type);
864 if ( ret < 0 )
865 return ret;
866
867 val += ret;
868
869 feat = info->features[feat_type];
870 if ( !feat )
871 return -ENOENT;
872
873 props = feat_props[feat_type];
874 if ( !props )
875 {
876 ASSERT_UNREACHABLE();
877 return -ENOENT;
878 }
879
880 if ( array_len < props->cos_num )
881 return -ENOSPC;
882
883 if ( !psr_check_cbm(feat->cbm_len, new_val) )
884 return -EINVAL;
885
886 /*
887 * Value setting position is same as feature array.
888 * For CDP, user may set both DATA and CODE to same value. For such case,
889 * user input 'PSR_CBM_TYPE_L3' as type. The alternative type of CDP is same
890 * as it. So we should set new_val to both of DATA and CODE under such case.
891 */
892 for ( i = 0; i < props->cos_num; i++ )
893 {
894 if ( type == props->type[i] )
895 {
896 val[i] = new_val;
897 ret = 0;
898 break;
899 }
900 else if ( type == props->alt_type )
901 val[i] = new_val;
902 else
903 ret = -EINVAL;
904 }
905
906 return ret;
907 }
908
compare_val(const uint32_t val[],const struct feat_node * feat,const struct feat_props * props,unsigned int cos)909 static int compare_val(const uint32_t val[],
910 const struct feat_node *feat,
911 const struct feat_props *props,
912 unsigned int cos)
913 {
914 unsigned int i;
915
916 for ( i = 0; i < props->cos_num; i++ )
917 {
918 uint32_t feat_val;
919
920 /* If cos is bigger than cos_max, we need compare default value. */
921 if ( cos > feat->cos_max )
922 {
923 /*
924 * COS ID 0 always stores the default value.
925 * For CDP:
926 * - DATA default value stored in cos_reg_val[0];
927 * - CODE default value stored in cos_reg_val[1].
928 */
929 feat_val = feat->cos_reg_val[i];
930
931 /*
932 * If cos is bigger than feature's cos_max, the val should be
933 * default value. Otherwise, it fails to find a COS ID. So we
934 * have to exit find flow.
935 */
936 if ( val[i] != feat_val )
937 return -EINVAL;
938 }
939 else
940 {
941 feat_val = feat->cos_reg_val[cos * props->cos_num + i];
942 if ( val[i] != feat_val )
943 return 0;
944 }
945 }
946
947 return 1;
948 }
949
find_cos(const uint32_t val[],unsigned int array_len,enum psr_feat_type feat_type,const struct psr_socket_info * info)950 static int find_cos(const uint32_t val[], unsigned int array_len,
951 enum psr_feat_type feat_type,
952 const struct psr_socket_info *info)
953 {
954 unsigned int cos, cos_max;
955 const unsigned int *ref = info->cos_ref;
956 const struct feat_node *feat;
957
958 /* cos_max is the one of the feature which is being set. */
959 feat = info->features[feat_type];
960 if ( !feat )
961 return -ENOENT;
962
963 cos_max = feat->cos_max;
964
965 for ( cos = 0; cos <= cos_max; cos++ )
966 {
967 const uint32_t *val_ptr = val;
968 unsigned int len = array_len, i;
969 int rc = 0;
970
971 if ( cos && !ref[cos] )
972 continue;
973
974 for ( i = 0; i < ARRAY_SIZE(info->features); i++ )
975 {
976 const struct feat_props *props = feat_props[i];
977
978 feat = info->features[i];
979 if ( !feat )
980 continue;
981
982 if ( !props )
983 {
984 ASSERT_UNREACHABLE();
985 return -ENOENT;
986 }
987
988 if ( len < props->cos_num )
989 return -ENOSPC;
990
991 /*
992 * Compare value according to feature array order.
993 * We must follow this order because value array is assembled
994 * as this order.
995 */
996 rc = compare_val(val_ptr, feat, props, cos);
997 if ( rc < 0 )
998 return rc;
999
1000 /* If fail to match, go to next cos to compare. */
1001 if ( !rc )
1002 break;
1003
1004 len -= props->cos_num;
1005 val_ptr += props->cos_num;
1006 }
1007
1008 /* For this COS ID all entries in the values array do match. Use it. */
1009 if ( rc )
1010 return cos;
1011 }
1012
1013 return -ENOENT;
1014 }
1015
fits_cos_max(const uint32_t val[],uint32_t array_len,const struct psr_socket_info * info,unsigned int cos)1016 static bool fits_cos_max(const uint32_t val[],
1017 uint32_t array_len,
1018 const struct psr_socket_info *info,
1019 unsigned int cos)
1020 {
1021 unsigned int i;
1022
1023 for ( i = 0; i < ARRAY_SIZE(info->features); i++ )
1024 {
1025 const struct feat_node *feat = info->features[i];
1026 const struct feat_props *props = feat_props[i];
1027
1028 if ( !feat )
1029 continue;
1030
1031 if ( !props )
1032 {
1033 ASSERT_UNREACHABLE();
1034 return false;
1035 }
1036
1037 if ( array_len < props->cos_num )
1038 return false;
1039
1040 if ( cos > feat->cos_max )
1041 {
1042 unsigned int j;
1043
1044 for ( j = 0; j < props->cos_num; j++ )
1045 {
1046 /* Get default value, the COS ID of which is zero. */
1047 uint32_t default_val = feat->cos_reg_val[j];
1048
1049 if ( val[j] != default_val )
1050 return false;
1051 }
1052 }
1053
1054 array_len -= props->cos_num;
1055 val += props->cos_num;
1056 }
1057
1058 return true;
1059 }
1060
pick_avail_cos(const struct psr_socket_info * info,const uint32_t val[],unsigned int array_len,unsigned int old_cos,enum psr_feat_type feat_type)1061 static int pick_avail_cos(const struct psr_socket_info *info,
1062 const uint32_t val[], unsigned int array_len,
1063 unsigned int old_cos,
1064 enum psr_feat_type feat_type)
1065 {
1066 unsigned int cos, cos_max = 0;
1067 const struct feat_node *feat;
1068 const unsigned int *ref = info->cos_ref;
1069
1070 /* cos_max is the one of the feature which is being set. */
1071 feat = info->features[feat_type];
1072 if ( !feat )
1073 return -ENOENT;
1074
1075 cos_max = feat->cos_max;
1076 if ( !cos_max )
1077 return -ENOENT;
1078
1079 /* We cannot use id 0 because it stores the default values. */
1080 if ( old_cos && ref[old_cos] == 1 &&
1081 fits_cos_max(val, array_len, info, old_cos) )
1082 return old_cos;
1083
1084 /* Find an unused one other than cos0. */
1085 for ( cos = 1; cos <= cos_max; cos++ )
1086 {
1087 /*
1088 * ref is 0 means this COS is not used by other domain and
1089 * can be used for current setting.
1090 */
1091 if ( !ref[cos] )
1092 {
1093 if ( !fits_cos_max(val, array_len, info, cos) )
1094 break;
1095
1096 return cos;
1097 }
1098 }
1099
1100 return -EOVERFLOW;
1101 }
1102
get_socket_cpu(unsigned int socket)1103 static unsigned int get_socket_cpu(unsigned int socket)
1104 {
1105 if ( likely(socket < nr_sockets) )
1106 return cpumask_any(socket_cpumask[socket]);
1107
1108 return nr_cpu_ids;
1109 }
1110
1111 struct cos_write_info
1112 {
1113 unsigned int cos;
1114 unsigned int array_len;
1115 const uint32_t *val;
1116 };
1117
do_write_psr_msrs(void * data)1118 static void do_write_psr_msrs(void *data)
1119 {
1120 const struct cos_write_info *info = data;
1121 unsigned int i, index, cos = info->cos;
1122 const struct psr_socket_info *socket_info =
1123 get_socket_info(cpu_to_socket(smp_processor_id()));
1124
1125 /*
1126 * Iterate all featuers to write different value (not same as MSR) for
1127 * each feature.
1128 */
1129 for ( index = i = 0; i < ARRAY_SIZE(feat_props); i++ )
1130 {
1131 struct feat_node *feat = socket_info->features[i];
1132 const struct feat_props *props = feat_props[i];
1133 unsigned int cos_num, j;
1134
1135 if ( !feat || !props )
1136 continue;
1137
1138 cos_num = props->cos_num;
1139 ASSERT(info->array_len >= index + cos_num);
1140
1141 for ( j = 0; j < cos_num; j++, index++ )
1142 {
1143 if ( feat->cos_reg_val[cos * cos_num + j] != info->val[index] )
1144 {
1145 feat->cos_reg_val[cos * cos_num + j] = info->val[index];
1146 props->write_msr(cos, info->val[index], props->type[j]);
1147 }
1148 }
1149 }
1150 }
1151
write_psr_msrs(unsigned int socket,unsigned int cos,const uint32_t val[],unsigned int array_len,enum psr_feat_type feat_type)1152 static int write_psr_msrs(unsigned int socket, unsigned int cos,
1153 const uint32_t val[], unsigned int array_len,
1154 enum psr_feat_type feat_type)
1155 {
1156 struct psr_socket_info *info = get_socket_info(socket);
1157 struct cos_write_info data =
1158 {
1159 .cos = cos,
1160 .val = val,
1161 .array_len = array_len,
1162 };
1163
1164 if ( cos > info->features[feat_type]->cos_max )
1165 return -EINVAL;
1166
1167 if ( socket == cpu_to_socket(smp_processor_id()) )
1168 do_write_psr_msrs(&data);
1169 else
1170 {
1171 unsigned int cpu = get_socket_cpu(socket);
1172
1173 if ( cpu >= nr_cpu_ids )
1174 return -ENOTSOCK;
1175 on_selected_cpus(cpumask_of(cpu), do_write_psr_msrs, &data, 1);
1176 }
1177
1178 return 0;
1179 }
1180
psr_set_val(struct domain * d,unsigned int socket,uint64_t new_val,enum cbm_type type)1181 int psr_set_val(struct domain *d, unsigned int socket,
1182 uint64_t new_val, enum cbm_type type)
1183 {
1184 unsigned int old_cos, array_len;
1185 int cos, ret;
1186 unsigned int *ref;
1187 uint32_t *val_array, val;
1188 struct psr_socket_info *info = get_socket_info(socket);
1189 enum psr_feat_type feat_type;
1190
1191 if ( IS_ERR(info) )
1192 return PTR_ERR(info);
1193
1194 val = new_val;
1195 if ( new_val != val )
1196 return -EINVAL;
1197
1198 feat_type = psr_cbm_type_to_feat_type(type);
1199 if ( feat_type >= ARRAY_SIZE(info->features) ||
1200 !info->features[feat_type] )
1201 return -ENOENT;
1202
1203 /*
1204 * Step 0:
1205 * old_cos means the COS ID current domain is using. By default, it is 0.
1206 *
1207 * For every COS ID, there is a reference count to record how many domains
1208 * are using the COS register corresponding to this COS ID.
1209 * - If ref[old_cos] is 0, that means this COS is not used by any domain.
1210 * - If ref[old_cos] is 1, that means this COS is only used by current
1211 * domain.
1212 * - If ref[old_cos] is more than 1, that mean multiple domains are using
1213 * this COS.
1214 */
1215 domain_lock(d);
1216 if ( !test_and_set_bit(d->domain_id, info->dom_set) )
1217 d->arch.psr_cos_ids[socket] = 0;
1218
1219 old_cos = d->arch.psr_cos_ids[socket];
1220 domain_unlock(d);
1221
1222 ASSERT(old_cos < MAX_COS_REG_CNT);
1223
1224 ref = info->cos_ref;
1225
1226 /*
1227 * Step 1:
1228 * Gather a value array to store all features cos_reg_val[old_cos].
1229 * And, set the input new val into array according to the feature's
1230 * position in array.
1231 */
1232 array_len = get_cos_num();
1233 val_array = xzalloc_array(uint32_t, array_len);
1234 if ( !val_array )
1235 return -ENOMEM;
1236
1237 if ( (ret = gather_val_array(val_array, array_len, info, old_cos)) != 0 )
1238 goto free_array;
1239
1240 if ( (ret = insert_val_into_array(val_array, array_len, info,
1241 feat_type, type, val)) != 0 )
1242 goto free_array;
1243
1244 spin_lock(&info->ref_lock);
1245
1246 /*
1247 * Step 2:
1248 * Try to find if there is already a COS ID on which all features' values
1249 * are same as the array. Then, we can reuse this COS ID.
1250 */
1251 cos = find_cos(val_array, array_len, feat_type, info);
1252 if ( cos == old_cos )
1253 {
1254 ret = 0;
1255 goto unlock_free_array;
1256 }
1257
1258 /*
1259 * Step 3:
1260 * If fail to find, we need pick an available COS ID.
1261 * In fact, only COS ID which ref is 1 or 0 can be picked for current
1262 * domain. If old_cos is not 0 and its ref==1, that means only current
1263 * domain is using this old_cos ID. So, this old_cos ID certainly can
1264 * be reused by current domain. Ref==0 means there is no any domain
1265 * using this COS ID. So it can be used for current domain too.
1266 */
1267 if ( cos < 0 )
1268 {
1269 cos = pick_avail_cos(info, val_array, array_len, old_cos, feat_type);
1270 if ( cos < 0 )
1271 {
1272 ret = cos;
1273 goto unlock_free_array;
1274 }
1275
1276 /*
1277 * Step 4:
1278 * Write the feature's MSRs according to the COS ID.
1279 */
1280 ret = write_psr_msrs(socket, cos, val_array, array_len, feat_type);
1281 if ( ret )
1282 goto unlock_free_array;
1283 }
1284
1285 /*
1286 * Step 5:
1287 * Find the COS ID (find_cos result is '>= 0' or an available COS ID is
1288 * picked, then update ref according to COS ID.
1289 */
1290 ref[cos]++;
1291 ASSERT(!cos || ref[cos]);
1292 ASSERT(!old_cos || ref[old_cos]);
1293 ref[old_cos]--;
1294 spin_unlock(&info->ref_lock);
1295
1296 /*
1297 * Step 6:
1298 * Save the COS ID into current domain's psr_cos_ids[] so that we can know
1299 * which COS the domain is using on the socket. One domain can only use
1300 * one COS ID at same time on each socket.
1301 */
1302 domain_lock(d);
1303 d->arch.psr_cos_ids[socket] = cos;
1304 domain_unlock(d);
1305
1306 goto free_array;
1307
1308 unlock_free_array:
1309 spin_unlock(&info->ref_lock);
1310
1311 free_array:
1312 xfree(val_array);
1313 return ret;
1314 }
1315
psr_free_cos(struct domain * d)1316 static void psr_free_cos(struct domain *d)
1317 {
1318 unsigned int socket, cos;
1319
1320 if ( !d->arch.psr_cos_ids )
1321 return;
1322
1323 ASSERT(socket_info);
1324
1325 /* Domain is destroyed so its cos_ref should be decreased. */
1326 for ( socket = 0; socket < nr_sockets; socket++ )
1327 {
1328 struct psr_socket_info *info = socket_info + socket;
1329
1330 clear_bit(d->domain_id, info->dom_set);
1331
1332 /* cos 0 is default one which does not need be handled. */
1333 cos = d->arch.psr_cos_ids[socket];
1334 if ( cos == 0 )
1335 continue;
1336
1337 spin_lock(&info->ref_lock);
1338 ASSERT(info->cos_ref[cos]);
1339 info->cos_ref[cos]--;
1340 spin_unlock(&info->ref_lock);
1341 }
1342
1343 xfree(d->arch.psr_cos_ids);
1344 d->arch.psr_cos_ids = NULL;
1345 }
1346
psr_alloc_cos(struct domain * d)1347 static void psr_alloc_cos(struct domain *d)
1348 {
1349 d->arch.psr_cos_ids = xzalloc_array(unsigned int, nr_sockets);
1350 if ( !d->arch.psr_cos_ids )
1351 printk(XENLOG_WARNING "Failed to alloc psr_cos_ids!\n");
1352 }
1353
psr_domain_init(struct domain * d)1354 void psr_domain_init(struct domain *d)
1355 {
1356 if ( psr_alloc_feat_enabled() )
1357 psr_alloc_cos(d);
1358 }
1359
psr_domain_free(struct domain * d)1360 void psr_domain_free(struct domain *d)
1361 {
1362 psr_free_rmid(d);
1363 psr_free_cos(d);
1364 }
1365
init_psr(void)1366 static void __init init_psr(void)
1367 {
1368 if ( opt_cos_max < 1 )
1369 {
1370 printk(XENLOG_INFO "CAT: disabled, cos_max is too small\n");
1371 return;
1372 }
1373
1374 socket_info = xzalloc_array(struct psr_socket_info, nr_sockets);
1375
1376 if ( !socket_info )
1377 {
1378 printk(XENLOG_WARNING "Failed to alloc socket_info!\n");
1379 return;
1380 }
1381 }
1382
psr_free(void)1383 static void __init psr_free(void)
1384 {
1385 xfree(socket_info);
1386 socket_info = NULL;
1387 }
1388
psr_cpu_prepare(void)1389 static int psr_cpu_prepare(void)
1390 {
1391 if ( !psr_alloc_feat_enabled() )
1392 return 0;
1393
1394 /* Malloc memory for the global feature node here. */
1395 if ( feat_l3 == NULL &&
1396 (feat_l3 = xzalloc(struct feat_node)) == NULL )
1397 return -ENOMEM;
1398
1399 if ( feat_l2_cat == NULL &&
1400 (feat_l2_cat = xzalloc(struct feat_node)) == NULL )
1401 return -ENOMEM;
1402
1403 return 0;
1404 }
1405
psr_cpu_init(void)1406 static void psr_cpu_init(void)
1407 {
1408 struct psr_socket_info *info;
1409 unsigned int socket, cpu = smp_processor_id();
1410 struct feat_node *feat;
1411 struct cpuid_leaf regs;
1412
1413 if ( !psr_alloc_feat_enabled() || !boot_cpu_has(X86_FEATURE_PQE) )
1414 goto assoc_init;
1415
1416 if ( boot_cpu_data.cpuid_level < PSR_CPUID_LEVEL_CAT )
1417 {
1418 setup_clear_cpu_cap(X86_FEATURE_PQE);
1419 goto assoc_init;
1420 }
1421
1422 socket = cpu_to_socket(cpu);
1423 info = socket_info + socket;
1424 if ( info->feat_init )
1425 goto assoc_init;
1426
1427 spin_lock_init(&info->ref_lock);
1428
1429 cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 0, ®s);
1430 if ( regs.b & PSR_RESOURCE_TYPE_L3 )
1431 {
1432 cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 1, ®s);
1433
1434 feat = feat_l3;
1435 feat_l3 = NULL;
1436
1437 if ( (regs.c & PSR_CAT_CDP_CAPABILITY) && (opt_psr & PSR_CDP) &&
1438 !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CDP) )
1439 feat_props[FEAT_TYPE_L3_CDP] = &l3_cdp_props;
1440
1441 /* If CDP init fails, try to work as L3 CAT. */
1442 if ( !feat_props[FEAT_TYPE_L3_CDP] )
1443 {
1444 if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CAT) )
1445 feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props;
1446 else
1447 feat_l3 = feat;
1448 }
1449 }
1450
1451 cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 0, ®s);
1452 if ( regs.b & PSR_RESOURCE_TYPE_L2 )
1453 {
1454 cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 2, ®s);
1455
1456 feat = feat_l2_cat;
1457 feat_l2_cat = NULL;
1458 if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L2_CAT) )
1459 feat_props[FEAT_TYPE_L2_CAT] = &l2_cat_props;
1460 else
1461 feat_l2_cat = feat;
1462 }
1463
1464 info->feat_init = true;
1465
1466 assoc_init:
1467 psr_assoc_init();
1468 }
1469
psr_cpu_fini(unsigned int cpu)1470 static void psr_cpu_fini(unsigned int cpu)
1471 {
1472 unsigned int socket = cpu_to_socket(cpu);
1473
1474 if ( !psr_alloc_feat_enabled() )
1475 return;
1476
1477 /*
1478 * We only free when we are the last CPU in the socket. The socket_cpumask
1479 * is cleared prior to this notification code by remove_siblinginfo().
1480 */
1481 if ( socket_cpumask[socket] && cpumask_empty(socket_cpumask[socket]) )
1482 free_socket_resources(socket);
1483 }
1484
cpu_callback(struct notifier_block * nfb,unsigned long action,void * hcpu)1485 static int cpu_callback(
1486 struct notifier_block *nfb, unsigned long action, void *hcpu)
1487 {
1488 int rc = 0;
1489 unsigned int cpu = (unsigned long)hcpu;
1490
1491 switch ( action )
1492 {
1493 case CPU_UP_PREPARE:
1494 rc = psr_cpu_prepare();
1495 break;
1496 case CPU_STARTING:
1497 psr_cpu_init();
1498 break;
1499 case CPU_UP_CANCELED:
1500 case CPU_DEAD:
1501 psr_cpu_fini(cpu);
1502 break;
1503 }
1504
1505 return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
1506 }
1507
1508 static struct notifier_block cpu_nfb = {
1509 .notifier_call = cpu_callback,
1510 /*
1511 * Ensure socket_cpumask is still valid in CPU_DEAD notification
1512 * (E.g. our CPU_DEAD notification should be called ahead of
1513 * cpu_smpboot_free).
1514 */
1515 .priority = -1
1516 };
1517
psr_presmp_init(void)1518 static int __init psr_presmp_init(void)
1519 {
1520 if ( (opt_psr & PSR_CMT) && opt_rmid_max )
1521 init_psr_cmt(opt_rmid_max);
1522
1523 if ( opt_psr & (PSR_CAT | PSR_CDP) )
1524 init_psr();
1525
1526 if ( psr_cpu_prepare() )
1527 psr_free();
1528
1529 psr_cpu_init();
1530 if ( psr_cmt_enabled() || psr_alloc_feat_enabled() )
1531 register_cpu_notifier(&cpu_nfb);
1532
1533 return 0;
1534 }
1535 presmp_initcall(psr_presmp_init);
1536
1537 /*
1538 * Local variables:
1539 * mode: C
1540 * c-file-style: "BSD"
1541 * c-basic-offset: 4
1542 * tab-width: 4
1543 * indent-tabs-mode: nil
1544 * End:
1545 */
1546