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(&reg, 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, &regs);
1430     if ( regs.b & PSR_RESOURCE_TYPE_L3 )
1431     {
1432         cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 1, &regs);
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(&regs, 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(&regs, 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, &regs);
1452     if ( regs.b & PSR_RESOURCE_TYPE_L2 )
1453     {
1454         cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 2, &regs);
1455 
1456         feat = feat_l2_cat;
1457         feat_l2_cat = NULL;
1458         if ( !cat_init_feature(&regs, 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