Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/psr.c
Line
Count
Source (jump to first uncovered line)
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
1
#define PSR_CMT        (1u << 0)
35
1
#define PSR_CAT        (1u << 1)
36
1
#define PSR_CDP        (1u << 2)
37
38
0
#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
0
#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
0
#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
0
            ((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
0
            ((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
 */
188
static bool psr_alloc_feat_enabled(void)
189
6
{
190
6
    return !!socket_info;
191
6
}
192
193
static void free_socket_resources(unsigned int socket)
194
0
{
195
0
    unsigned int i;
196
0
    struct psr_socket_info *info = socket_info + socket;
197
0
198
0
    ASSERT(socket_info);
199
0
200
0
    /*
201
0
     * Free resources of features. The global feature object, e.g. feat_l3,
202
0
     * may not be freed here if it is not added into array. It is simply being
203
0
     * kept until the next CPU online attempt.
204
0
     */
205
0
    for ( i = 0; i < ARRAY_SIZE(info->features); i++ )
206
0
    {
207
0
        xfree(info->features[i]);
208
0
        info->features[i] = NULL;
209
0
    }
210
0
211
0
    info->feat_init = false;
212
0
213
0
    memset(info->cos_ref, 0, MAX_COS_REG_CNT * sizeof(unsigned int));
214
0
215
0
    bitmap_zero(info->dom_set, DOMID_IDLE + 1);
216
0
}
217
218
static enum psr_feat_type psr_cbm_type_to_feat_type(enum cbm_type type)
219
0
{
220
0
    enum psr_feat_type feat_type = FEAT_TYPE_UNKNOWN;
221
0
222
0
    switch ( type )
223
0
    {
224
0
    case PSR_CBM_TYPE_L3:
225
0
        feat_type = FEAT_TYPE_L3_CAT;
226
0
227
0
        /*
228
0
         * If type is L3 CAT but we cannot find it in feat_props array,
229
0
         * try CDP.
230
0
         */
231
0
        if ( !feat_props[feat_type] )
232
0
            feat_type = FEAT_TYPE_L3_CDP;
233
0
234
0
        break;
235
0
236
0
    case PSR_CBM_TYPE_L3_DATA:
237
0
    case PSR_CBM_TYPE_L3_CODE:
238
0
        feat_type = FEAT_TYPE_L3_CDP;
239
0
        break;
240
0
241
0
    case PSR_CBM_TYPE_L2:
242
0
        feat_type = FEAT_TYPE_L2_CAT;
243
0
        break;
244
0
245
0
    default:
246
0
        ASSERT_UNREACHABLE();
247
0
    }
248
0
249
0
    return feat_type;
250
0
}
251
252
static bool psr_check_cbm(unsigned int cbm_len, unsigned long cbm)
253
0
{
254
0
    unsigned int first_bit, zero_bit;
255
0
256
0
    /* Set bits should only in the range of [0, cbm_len]. */
257
0
    if ( cbm & (~0ul << cbm_len) )
258
0
        return false;
259
0
260
0
    /* At least one bit need to be set. */
261
0
    if ( cbm == 0 )
262
0
        return false;
263
0
264
0
    first_bit = find_first_bit(&cbm, cbm_len);
265
0
    zero_bit = find_next_zero_bit(&cbm, cbm_len, first_bit);
266
0
267
0
    /* Set bits should be contiguous. */
268
0
    if ( zero_bit < cbm_len &&
269
0
         find_next_bit(&cbm, cbm_len, zero_bit) < cbm_len )
270
0
        return false;
271
0
272
0
    return true;
273
0
}
274
275
/* CAT common functions implementation. */
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
0
{
281
0
    const char *const cat_feat_name[FEAT_TYPE_NUM] = {
282
0
        [FEAT_TYPE_L3_CAT] = "L3 CAT",
283
0
        [FEAT_TYPE_L3_CDP] = "L3 CDP",
284
0
        [FEAT_TYPE_L2_CAT] = "L2 CAT",
285
0
    };
286
0
287
0
    /* No valid value so do not enable feature. */
288
0
    if ( !regs->a || !regs->d )
289
0
        return -ENOENT;
290
0
291
0
    feat->cbm_len = (regs->a & CAT_CBM_LEN_MASK) + 1;
292
0
    feat->cos_max = min(opt_cos_max, regs->d & CAT_COS_MAX_MASK);
293
0
294
0
    switch ( type )
295
0
    {
296
0
    case FEAT_TYPE_L3_CAT:
297
0
    case FEAT_TYPE_L2_CAT:
298
0
        if ( feat->cos_max < 1 )
299
0
            return -ENOENT;
300
0
301
0
        /* We reserve cos=0 as default cbm (all bits within cbm_len are 1). */
302
0
        feat->cos_reg_val[0] = cat_default_val(feat->cbm_len);
303
0
304
0
        wrmsrl((type == FEAT_TYPE_L3_CAT ?
305
0
                MSR_IA32_PSR_L3_MASK(0) :
306
0
                MSR_IA32_PSR_L2_MASK(0)),
307
0
               cat_default_val(feat->cbm_len));
308
0
309
0
        break;
310
0
311
0
    case FEAT_TYPE_L3_CDP:
312
0
    {
313
0
        uint64_t val;
314
0
315
0
        if ( feat->cos_max < 3 )
316
0
            return -ENOENT;
317
0
318
0
        /* Cut half of cos_max when CDP is enabled. */
319
0
        feat->cos_max = (feat->cos_max - 1) >> 1;
320
0
321
0
        /* We reserve cos=0 as default cbm (all bits within cbm_len are 1). */
322
0
        get_cdp_code(feat, 0) = cat_default_val(feat->cbm_len);
323
0
        get_cdp_data(feat, 0) = cat_default_val(feat->cbm_len);
324
0
325
0
        wrmsrl(MSR_IA32_PSR_L3_MASK(0), cat_default_val(feat->cbm_len));
326
0
        wrmsrl(MSR_IA32_PSR_L3_MASK(1), cat_default_val(feat->cbm_len));
327
0
        rdmsrl(MSR_IA32_PSR_L3_QOS_CFG, val);
328
0
        wrmsrl(MSR_IA32_PSR_L3_QOS_CFG,
329
0
               val | (1ull << PSR_L3_QOS_CDP_ENABLE_BIT));
330
0
331
0
        break;
332
0
    }
333
0
334
0
    default:
335
0
        return -ENOENT;
336
0
    }
337
0
338
0
    /* Add this feature into array. */
339
0
    info->features[type] = feat;
340
0
341
0
    if ( !opt_cpu_info )
342
0
        return 0;
343
0
344
0
    printk(XENLOG_INFO "%s: enabled on socket %u, cos_max:%u, cbm_len:%u\n",
345
0
           cat_feat_name[type], cpu_to_socket(smp_processor_id()),
346
0
           feat->cos_max, feat->cbm_len);
347
0
348
0
    return 0;
349
0
}
350
351
static bool cat_get_feat_info(const struct feat_node *feat,
352
                              uint32_t data[], unsigned int array_len)
353
0
{
354
0
    if ( array_len != PSR_INFO_ARRAY_SIZE )
355
0
        return false;
356
0
357
0
    data[PSR_INFO_IDX_COS_MAX] = feat->cos_max;
358
0
    data[PSR_INFO_IDX_CAT_CBM_LEN] = feat->cbm_len;
359
0
    data[PSR_INFO_IDX_CAT_FLAG] = 0;
360
0
361
0
    return true;
362
0
}
363
364
/* L3 CAT props */
365
static void l3_cat_write_msr(unsigned int cos, uint32_t val, enum cbm_type type)
366
0
{
367
0
    wrmsrl(MSR_IA32_PSR_L3_MASK(cos), val);
368
0
}
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 */
379
static bool l3_cdp_get_feat_info(const struct feat_node *feat,
380
                                 uint32_t data[], uint32_t array_len)
381
0
{
382
0
    if ( !cat_get_feat_info(feat, data, array_len) )
383
0
        return false;
384
0
385
0
    data[PSR_INFO_IDX_CAT_FLAG] |= XEN_SYSCTL_PSR_CAT_L3_CDP;
386
0
387
0
    return true;
388
0
}
389
390
static void l3_cdp_write_msr(unsigned int cos, uint32_t val, enum cbm_type type)
391
0
{
392
0
    wrmsrl(((type == PSR_CBM_TYPE_L3_DATA) ?
393
0
            MSR_IA32_PSR_L3_MASK_DATA(cos) :
394
0
            MSR_IA32_PSR_L3_MASK_CODE(cos)),
395
0
           val);
396
0
}
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 */
408
static void l2_cat_write_msr(unsigned int cos, uint32_t val, enum cbm_type type)
409
0
{
410
0
    wrmsrl(MSR_IA32_PSR_L2_MASK(cos), val);
411
0
}
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
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
0
{
425
0
    /* If cmdline is 'psr=', we need make sure delim != s */
426
0
    if ( delim != s && !strncmp(s, feature, delim - s) )
427
0
    {
428
0
        if ( !*delim || *delim == ',' )
429
0
            opt_psr |= mask;
430
0
        else
431
0
        {
432
0
            int val_int = parse_bool(delim + 1, ss);
433
0
434
0
            if ( val_int == 0 )
435
0
                opt_psr &= ~mask;
436
0
            else if ( val_int == 1 )
437
0
                opt_psr |= mask;
438
0
            else
439
0
                return false;
440
0
        }
441
0
        return true;
442
0
    }
443
0
    return false;
444
0
}
445
446
static int __init parse_psr_param(const char *s)
447
0
{
448
0
    const char *ss, *val_delim;
449
0
    const char *q;
450
0
    int rc = 0;
451
0
452
0
    do {
453
0
        ss = strchr(s, ',');
454
0
        if ( !ss )
455
0
            ss = strchr(s, '\0');
456
0
457
0
        val_delim = strchr(s, ':');
458
0
        if ( !val_delim )
459
0
            val_delim = strchr(s, '\0');
460
0
461
0
        /* E.g. 'psr=cmt,rmid_max:200' */
462
0
        if ( val_delim > ss )
463
0
            val_delim = ss;
464
0
465
0
        if ( *val_delim && !strncmp(s, "rmid_max", val_delim - s) )
466
0
        {
467
0
            opt_rmid_max = simple_strtoul(val_delim + 1, &q, 0);
468
0
            if ( *q && *q != ',' )
469
0
                rc = -EINVAL;
470
0
        }
471
0
        else if ( *val_delim && !strncmp(s, "cos_max", val_delim - s) )
472
0
        {
473
0
            opt_cos_max = simple_strtoul(val_delim + 1, &q, 0);
474
0
            if ( *q && *q != ',' )
475
0
                rc = -EINVAL;
476
0
        }
477
0
        else if ( !parse_psr_bool(s, val_delim, ss, "cmt", PSR_CMT) &&
478
0
                  !parse_psr_bool(s, val_delim, ss, "cat", PSR_CAT) &&
479
0
                  !parse_psr_bool(s, val_delim, ss, "cdp", PSR_CDP) )
480
0
            rc = -EINVAL;
481
0
482
0
        s = ss + 1;
483
0
    } while ( *ss );
484
0
485
0
    return rc;
486
0
}
487
custom_param("psr", parse_psr_param);
488
489
static void __init init_psr_cmt(unsigned int rmid_max)
490
0
{
491
0
    unsigned int eax, ebx, ecx, edx;
492
0
    unsigned int rmid;
493
0
494
0
    if ( !boot_cpu_has(X86_FEATURE_PQM) )
495
0
        return;
496
0
497
0
    cpuid_count(0xf, 0, &eax, &ebx, &ecx, &edx);
498
0
    if ( !edx )
499
0
        return;
500
0
501
0
    psr_cmt = xzalloc(struct psr_cmt);
502
0
    if ( !psr_cmt )
503
0
        return;
504
0
505
0
    psr_cmt->features = edx;
506
0
    psr_cmt->rmid_max = min(rmid_max, ebx);
507
0
    rmid_mask = ~(~0ull << get_count_order(ebx));
508
0
509
0
    if ( psr_cmt->features & PSR_RESOURCE_TYPE_L3 )
510
0
    {
511
0
        cpuid_count(0xf, 1, &eax, &ebx, &ecx, &edx);
512
0
        psr_cmt->l3.upscaling_factor = ebx;
513
0
        psr_cmt->l3.rmid_max = ecx;
514
0
        psr_cmt->l3.features = edx;
515
0
    }
516
0
517
0
    psr_cmt->rmid_max = min(psr_cmt->rmid_max, psr_cmt->l3.rmid_max);
518
0
    psr_cmt->rmid_to_dom = xmalloc_array(domid_t, psr_cmt->rmid_max + 1UL);
519
0
    if ( !psr_cmt->rmid_to_dom )
520
0
    {
521
0
        xfree(psr_cmt);
522
0
        psr_cmt = NULL;
523
0
        return;
524
0
    }
525
0
526
0
    /*
527
0
     * Once CMT is enabled each CPU will always require a RMID to associate
528
0
     * with it. To reduce the waste of RMID, reserve RMID 0 for all CPUs that
529
0
     * have no domain being monitored.
530
0
     */
531
0
    psr_cmt->rmid_to_dom[0] = DOMID_XEN;
532
0
    for ( rmid = 1; rmid <= psr_cmt->rmid_max; rmid++ )
533
0
        psr_cmt->rmid_to_dom[rmid] = DOMID_INVALID;
534
0
535
0
    printk(XENLOG_INFO "Cache Monitoring Technology enabled\n");
536
0
}
537
538
/* Called with domain lock held, no psr specific lock needed */
539
int psr_alloc_rmid(struct domain *d)
540
0
{
541
0
    unsigned int rmid;
542
0
543
0
    ASSERT(psr_cmt_enabled());
544
0
545
0
    if ( d->arch.psr_rmid > 0 )
546
0
        return -EEXIST;
547
0
548
0
    for ( rmid = 1; rmid <= psr_cmt->rmid_max; rmid++ )
549
0
    {
550
0
        if ( psr_cmt->rmid_to_dom[rmid] != DOMID_INVALID )
551
0
            continue;
552
0
553
0
        psr_cmt->rmid_to_dom[rmid] = d->domain_id;
554
0
        break;
555
0
    }
556
0
557
0
    /* No RMID available, assign RMID=0 by default. */
558
0
    if ( rmid > psr_cmt->rmid_max )
559
0
    {
560
0
        d->arch.psr_rmid = 0;
561
0
        return -EOVERFLOW;
562
0
    }
563
0
564
0
    d->arch.psr_rmid = rmid;
565
0
566
0
    return 0;
567
0
}
568
569
/* Called with domain lock held, no psr specific lock needed */
570
void psr_free_rmid(struct domain *d)
571
0
{
572
0
    unsigned int rmid;
573
0
574
0
    rmid = d->arch.psr_rmid;
575
0
    /* We do not free system reserved "RMID=0". */
576
0
    if ( rmid == 0 )
577
0
        return;
578
0
579
0
    psr_cmt->rmid_to_dom[rmid] = DOMID_INVALID;
580
0
    d->arch.psr_rmid = 0;
581
0
}
582
583
static unsigned int get_max_cos_max(const struct psr_socket_info *info)
584
0
{
585
0
    unsigned int cos_max = 0, i;
586
0
587
0
    for ( i = 0; i < ARRAY_SIZE(info->features); i++ )
588
0
    {
589
0
        const struct feat_node *feat = info->features[i];
590
0
591
0
        if ( feat )
592
0
            cos_max = max(feat->cos_max, cos_max);
593
0
    }
594
0
595
0
    return cos_max;
596
0
}
597
598
static void psr_assoc_init(void)
599
1
{
600
1
    struct psr_assoc *psra = &this_cpu(psr_assoc);
601
1
602
1
    if ( psr_alloc_feat_enabled() )
603
0
    {
604
0
        unsigned int socket = cpu_to_socket(smp_processor_id());
605
0
        const struct psr_socket_info *info = socket_info + socket;
606
0
        unsigned int cos_max = get_max_cos_max(info);
607
0
608
0
        if ( info->feat_init )
609
0
            psra->cos_mask = ((1ull << get_count_order(cos_max)) - 1) <<
610
0
                             ASSOC_REG_SHIFT;
611
0
    }
612
1
613
1
    if ( psr_cmt_enabled() || psra->cos_mask )
614
0
        rdmsrl(MSR_IA32_PSR_ASSOC, psra->val);
615
1
}
616
617
static inline void psr_assoc_rmid(uint64_t *reg, unsigned int rmid)
618
0
{
619
0
    *reg = (*reg & ~rmid_mask) | (rmid & rmid_mask);
620
0
}
621
622
static uint64_t psr_assoc_cos(uint64_t reg, unsigned int cos,
623
                              uint64_t cos_mask)
624
0
{
625
0
    return (reg & ~cos_mask) |
626
0
            (((uint64_t)cos << ASSOC_REG_SHIFT) & cos_mask);
627
0
}
628
629
void psr_ctxt_switch_to(struct domain *d)
630
39.5k
{
631
39.5k
    struct psr_assoc *psra = &this_cpu(psr_assoc);
632
39.5k
    uint64_t reg = psra->val;
633
39.5k
634
39.5k
    if ( psr_cmt_enabled() )
635
0
        psr_assoc_rmid(&reg, d->arch.psr_rmid);
636
39.5k
637
39.5k
    /*
638
39.5k
     * If the domain is not set in 'dom_set' bitmap, that means the domain's
639
39.5k
     * cos id is not valid. So, we have to use default value (0) to set ASSOC
640
39.5k
     * register. Furthermore, if domain's 'psr_cos_ids' is NULL, we need
641
39.5k
     * default value for it too (for case that the domain's psr_cos_ids is not
642
39.5k
     * successfully allocated).
643
39.5k
     */
644
39.5k
    if ( psra->cos_mask )
645
0
    {
646
0
        unsigned int socket = cpu_to_socket(smp_processor_id());
647
0
        struct psr_socket_info *info = socket_info + socket;
648
0
        unsigned int cos = 0;
649
0
650
0
        if ( likely(test_bit(d->domain_id, info->dom_set)) &&
651
0
             d->arch.psr_cos_ids )
652
0
            cos = d->arch.psr_cos_ids[socket];
653
0
654
0
        reg = psr_assoc_cos(reg, cos, psra->cos_mask);
655
0
    }
656
39.5k
657
39.5k
    if ( reg != psra->val )
658
0
    {
659
0
        wrmsrl(MSR_IA32_PSR_ASSOC, reg);
660
0
        psra->val = reg;
661
0
    }
662
39.5k
}
663
664
static struct psr_socket_info *get_socket_info(unsigned int socket)
665
0
{
666
0
    if ( !socket_info )
667
0
        return ERR_PTR(-ENODEV);
668
0
669
0
    if ( socket >= nr_sockets )
670
0
        return ERR_PTR(-ERANGE);
671
0
672
0
    if ( !socket_info[socket].feat_init )
673
0
        return ERR_PTR(-ENOENT);
674
0
675
0
    return socket_info + socket;
676
0
}
677
678
int psr_get_info(unsigned int socket, enum cbm_type type,
679
                 uint32_t data[], unsigned int array_len)
680
0
{
681
0
    const struct psr_socket_info *info = get_socket_info(socket);
682
0
    const struct feat_node *feat;
683
0
    enum psr_feat_type feat_type;
684
0
685
0
    ASSERT(data);
686
0
687
0
    if ( IS_ERR(info) )
688
0
        return PTR_ERR(info);
689
0
690
0
    feat_type = psr_cbm_type_to_feat_type(type);
691
0
    if ( feat_type >= ARRAY_SIZE(info->features) )
692
0
        return -ENOENT;
693
0
694
0
    feat = info->features[feat_type];
695
0
    if ( !feat )
696
0
        return -ENOENT;
697
0
698
0
    if ( !feat_props[feat_type] )
699
0
    {
700
0
        ASSERT_UNREACHABLE();
701
0
        return -ENOENT;
702
0
    }
703
0
704
0
    if ( feat_props[feat_type]->get_feat_info(feat, data, array_len) )
705
0
        return 0;
706
0
707
0
    return -EINVAL;
708
0
}
709
710
int psr_get_val(struct domain *d, unsigned int socket,
711
                uint32_t *val, enum cbm_type type)
712
0
{
713
0
    const struct psr_socket_info *info = get_socket_info(socket);
714
0
    const struct feat_node *feat;
715
0
    enum psr_feat_type feat_type;
716
0
    unsigned int cos, i;
717
0
718
0
    ASSERT(val);
719
0
720
0
    if ( IS_ERR(info) )
721
0
        return PTR_ERR(info);
722
0
723
0
    feat_type = psr_cbm_type_to_feat_type(type);
724
0
    if ( feat_type >= ARRAY_SIZE(info->features) )
725
0
        return -ENOENT;
726
0
727
0
    feat = info->features[feat_type];
728
0
    if ( !feat )
729
0
        return -ENOENT;
730
0
731
0
    if ( !feat_props[feat_type] )
732
0
    {
733
0
        ASSERT_UNREACHABLE();
734
0
        return -ENOENT;
735
0
    }
736
0
737
0
    domain_lock(d);
738
0
    if ( !test_and_set_bit(d->domain_id, socket_info[socket].dom_set) )
739
0
        d->arch.psr_cos_ids[socket] = 0;
740
0
741
0
    cos = d->arch.psr_cos_ids[socket];
742
0
    domain_unlock(d);
743
0
744
0
    /*
745
0
     * If input cos exceeds current feature's cos_max, we should return its
746
0
     * default value which is stored in cos 0. This case only happens
747
0
     * when more than two features enabled concurrently and at least one
748
0
     * features's cos_max is bigger than others. When a domain's working cos
749
0
     * id is bigger than some features' cos_max, HW automatically works as
750
0
     * default value for those features which cos_max is smaller.
751
0
     */
752
0
    if ( cos > feat->cos_max )
753
0
        cos = 0;
754
0
755
0
    for ( i = 0; i < feat_props[feat_type]->cos_num; i++ )
756
0
    {
757
0
        if ( type == feat_props[feat_type]->type[i] )
758
0
        {
759
0
            *val = feat->cos_reg_val[cos * feat_props[feat_type]->cos_num + i];
760
0
            return 0;
761
0
        }
762
0
    }
763
0
764
0
    return -EINVAL;
765
0
}
766
767
/* Set value functions */
768
static unsigned int get_cos_num(void)
769
0
{
770
0
    unsigned int num = 0, i;
771
0
772
0
    /* Get all features total amount. */
773
0
    for ( i = 0; i < ARRAY_SIZE(feat_props); i++ )
774
0
        if ( feat_props[i] )
775
0
            num += feat_props[i]->cos_num;
776
0
777
0
    return num;
778
0
}
779
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
0
{
785
0
    unsigned int i;
786
0
787
0
    if ( !val )
788
0
        return -EINVAL;
789
0
790
0
    /* Get all features current values according to old_cos. */
791
0
    for ( i = 0; i < ARRAY_SIZE(info->features); i++ )
792
0
    {
793
0
        unsigned int cos = old_cos, j;
794
0
        const struct feat_node *feat = info->features[i];
795
0
        const struct feat_props *props = feat_props[i];
796
0
797
0
        if ( !feat )
798
0
            continue;
799
0
800
0
        if ( !props )
801
0
        {
802
0
            ASSERT_UNREACHABLE();
803
0
            return -ENOENT;
804
0
        }
805
0
806
0
        if ( array_len < props->cos_num )
807
0
            return -ENOSPC;
808
0
809
0
        /*
810
0
         * If old_cos exceeds current feature's cos_max, we should get
811
0
         * default value. So assign cos to 0 which stores default value.
812
0
         */
813
0
        if ( cos > feat->cos_max )
814
0
            cos = 0;
815
0
816
0
        /* Value getting order is same as feature array. */
817
0
        for ( j = 0; j < props->cos_num; j++ )
818
0
            val[j] = feat->cos_reg_val[cos * props->cos_num + j];
819
0
820
0
        array_len -= props->cos_num;
821
0
        val += props->cos_num;
822
0
    }
823
0
824
0
    return 0;
825
0
}
826
827
static int skip_prior_features(unsigned int *array_len,
828
                               enum psr_feat_type feat_type)
829
0
{
830
0
    unsigned int i, skip_len = 0;
831
0
832
0
    for ( i = 0; i < feat_type; i++ )
833
0
    {
834
0
        const struct feat_props *props = feat_props[i];
835
0
836
0
        if ( !props )
837
0
            continue;
838
0
839
0
        if ( *array_len <= props->cos_num )
840
0
            return -ENOSPC;
841
0
842
0
        *array_len -= props->cos_num;
843
0
        skip_len += props->cos_num;
844
0
    }
845
0
846
0
    return skip_len;
847
0
}
848
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
0
{
856
0
    const struct feat_node *feat;
857
0
    const struct feat_props *props;
858
0
    unsigned int i;
859
0
    int ret;
860
0
861
0
    ASSERT(feat_type < FEAT_TYPE_NUM);
862
0
863
0
    ret = skip_prior_features(&array_len, feat_type);
864
0
    if ( ret < 0 )
865
0
        return ret;
866
0
867
0
    val += ret;
868
0
869
0
    feat = info->features[feat_type];
870
0
    if ( !feat )
871
0
        return -ENOENT;
872
0
873
0
    props = feat_props[feat_type];
874
0
    if ( !props )
875
0
    {
876
0
        ASSERT_UNREACHABLE();
877
0
        return -ENOENT;
878
0
    }
879
0
880
0
    if ( array_len < props->cos_num )
881
0
        return -ENOSPC;
882
0
883
0
    if ( !psr_check_cbm(feat->cbm_len, new_val) )
884
0
        return -EINVAL;
885
0
886
0
    /*
887
0
     * Value setting position is same as feature array.
888
0
     * For CDP, user may set both DATA and CODE to same value. For such case,
889
0
     * user input 'PSR_CBM_TYPE_L3' as type. The alternative type of CDP is same
890
0
     * as it. So we should set new_val to both of DATA and CODE under such case.
891
0
     */
892
0
    for ( i = 0; i < props->cos_num; i++ )
893
0
    {
894
0
        if ( type == props->type[i] )
895
0
        {
896
0
            val[i] = new_val;
897
0
            ret = 0;
898
0
            break;
899
0
        }
900
0
        else if ( type == props->alt_type )
901
0
            val[i] = new_val;
902
0
        else
903
0
            ret = -EINVAL;
904
0
    }
905
0
906
0
    return ret;
907
0
}
908
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
0
{
914
0
    unsigned int i;
915
0
916
0
    for ( i = 0; i < props->cos_num; i++ )
917
0
    {
918
0
        uint32_t feat_val;
919
0
920
0
        /* If cos is bigger than cos_max, we need compare default value. */
921
0
        if ( cos > feat->cos_max )
922
0
        {
923
0
            /*
924
0
             * COS ID 0 always stores the default value.
925
0
             * For CDP:
926
0
             * - DATA default value stored in cos_reg_val[0];
927
0
             * - CODE default value stored in cos_reg_val[1].
928
0
             */
929
0
            feat_val = feat->cos_reg_val[i];
930
0
931
0
            /*
932
0
             * If cos is bigger than feature's cos_max, the val should be
933
0
             * default value. Otherwise, it fails to find a COS ID. So we
934
0
             * have to exit find flow.
935
0
             */
936
0
            if ( val[i] != feat_val )
937
0
                return -EINVAL;
938
0
        }
939
0
        else
940
0
        {
941
0
            feat_val = feat->cos_reg_val[cos * props->cos_num + i];
942
0
            if ( val[i] != feat_val )
943
0
                return 0;
944
0
        }
945
0
    }
946
0
947
0
    return 1;
948
0
}
949
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
0
{
954
0
    unsigned int cos, cos_max;
955
0
    const unsigned int *ref = info->cos_ref;
956
0
    const struct feat_node *feat;
957
0
958
0
    /* cos_max is the one of the feature which is being set. */
959
0
    feat = info->features[feat_type];
960
0
    if ( !feat )
961
0
        return -ENOENT;
962
0
963
0
    cos_max = feat->cos_max;
964
0
965
0
    for ( cos = 0; cos <= cos_max; cos++ )
966
0
    {
967
0
        const uint32_t *val_ptr = val;
968
0
        unsigned int len = array_len, i;
969
0
        int rc = 0;
970
0
971
0
        if ( cos && !ref[cos] )
972
0
            continue;
973
0
974
0
        for ( i = 0; i < ARRAY_SIZE(info->features); i++ )
975
0
        {
976
0
            const struct feat_props *props = feat_props[i];
977
0
978
0
            feat = info->features[i];
979
0
            if ( !feat )
980
0
                continue;
981
0
982
0
            if ( !props )
983
0
            {
984
0
                ASSERT_UNREACHABLE();
985
0
                return -ENOENT;
986
0
            }
987
0
988
0
            if ( len < props->cos_num )
989
0
                return -ENOSPC;
990
0
991
0
            /*
992
0
             * Compare value according to feature array order.
993
0
             * We must follow this order because value array is assembled
994
0
             * as this order.
995
0
             */
996
0
            rc = compare_val(val_ptr, feat, props, cos);
997
0
            if ( rc < 0 )
998
0
                return rc;
999
0
1000
0
            /* If fail to match, go to next cos to compare. */
1001
0
            if ( !rc )
1002
0
                break;
1003
0
1004
0
            len -= props->cos_num;
1005
0
            val_ptr += props->cos_num;
1006
0
        }
1007
0
1008
0
        /* For this COS ID all entries in the values array do match. Use it. */
1009
0
        if ( rc )
1010
0
            return cos;
1011
0
    }
1012
0
1013
0
    return -ENOENT;
1014
0
}
1015
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
0
{
1021
0
    unsigned int i;
1022
0
1023
0
    for ( i = 0; i < ARRAY_SIZE(info->features); i++ )
1024
0
    {
1025
0
        const struct feat_node *feat = info->features[i];
1026
0
        const struct feat_props *props = feat_props[i];
1027
0
1028
0
        if ( !feat )
1029
0
            continue;
1030
0
1031
0
        if ( !props )
1032
0
        {
1033
0
            ASSERT_UNREACHABLE();
1034
0
            return false;
1035
0
        }
1036
0
1037
0
        if ( array_len < props->cos_num )
1038
0
            return false;
1039
0
1040
0
        if ( cos > feat->cos_max )
1041
0
        {
1042
0
            unsigned int j;
1043
0
1044
0
            for ( j = 0; j < props->cos_num; j++ )
1045
0
            {
1046
0
                /* Get default value, the COS ID of which is zero. */
1047
0
                uint32_t default_val = feat->cos_reg_val[j];
1048
0
1049
0
                if ( val[j] != default_val )
1050
0
                    return false;
1051
0
            }
1052
0
        }
1053
0
1054
0
        array_len -= props->cos_num;
1055
0
        val += props->cos_num;
1056
0
    }
1057
0
1058
0
    return true;
1059
0
}
1060
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
0
{
1066
0
    unsigned int cos, cos_max = 0;
1067
0
    const struct feat_node *feat;
1068
0
    const unsigned int *ref = info->cos_ref;
1069
0
1070
0
    /* cos_max is the one of the feature which is being set. */
1071
0
    feat = info->features[feat_type];
1072
0
    if ( !feat )
1073
0
        return -ENOENT;
1074
0
1075
0
    cos_max = feat->cos_max;
1076
0
    if ( !cos_max )
1077
0
        return -ENOENT;
1078
0
1079
0
    /* We cannot use id 0 because it stores the default values. */
1080
0
    if ( old_cos && ref[old_cos] == 1 &&
1081
0
         fits_cos_max(val, array_len, info, old_cos) )
1082
0
            return old_cos;
1083
0
1084
0
    /* Find an unused one other than cos0. */
1085
0
    for ( cos = 1; cos <= cos_max; cos++ )
1086
0
    {
1087
0
        /*
1088
0
         * ref is 0 means this COS is not used by other domain and
1089
0
         * can be used for current setting.
1090
0
         */
1091
0
        if ( !ref[cos] )
1092
0
        {
1093
0
            if ( !fits_cos_max(val, array_len, info, cos) )
1094
0
                break;
1095
0
1096
0
            return cos;
1097
0
        }
1098
0
    }
1099
0
1100
0
    return -EOVERFLOW;
1101
0
}
1102
1103
static unsigned int get_socket_cpu(unsigned int socket)
1104
0
{
1105
0
    if ( likely(socket < nr_sockets) )
1106
0
        return cpumask_any(socket_cpumask[socket]);
1107
0
1108
0
    return nr_cpu_ids;
1109
0
}
1110
1111
struct cos_write_info
1112
{
1113
    unsigned int cos;
1114
    unsigned int array_len;
1115
    const uint32_t *val;
1116
};
1117
1118
static void do_write_psr_msrs(void *data)
1119
0
{
1120
0
    const struct cos_write_info *info = data;
1121
0
    unsigned int i, index, cos = info->cos;
1122
0
    const struct psr_socket_info *socket_info =
1123
0
        get_socket_info(cpu_to_socket(smp_processor_id()));
1124
0
1125
0
    /*
1126
0
     * Iterate all featuers to write different value (not same as MSR) for
1127
0
     * each feature.
1128
0
     */
1129
0
    for ( index = i = 0; i < ARRAY_SIZE(feat_props); i++ )
1130
0
    {
1131
0
        struct feat_node *feat = socket_info->features[i];
1132
0
        const struct feat_props *props = feat_props[i];
1133
0
        unsigned int cos_num, j;
1134
0
1135
0
        if ( !feat || !props )
1136
0
            continue;
1137
0
1138
0
        cos_num = props->cos_num;
1139
0
        ASSERT(info->array_len >= index + cos_num);
1140
0
1141
0
        for ( j = 0; j < cos_num; j++, index++ )
1142
0
        {
1143
0
            if ( feat->cos_reg_val[cos * cos_num + j] != info->val[index] )
1144
0
            {
1145
0
                feat->cos_reg_val[cos * cos_num + j] = info->val[index];
1146
0
                props->write_msr(cos, info->val[index], props->type[j]);
1147
0
            }
1148
0
        }
1149
0
    }
1150
0
}
1151
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
0
{
1156
0
    struct psr_socket_info *info = get_socket_info(socket);
1157
0
    struct cos_write_info data =
1158
0
    {
1159
0
        .cos = cos,
1160
0
        .val = val,
1161
0
        .array_len = array_len,
1162
0
    };
1163
0
1164
0
    if ( cos > info->features[feat_type]->cos_max )
1165
0
        return -EINVAL;
1166
0
1167
0
    if ( socket == cpu_to_socket(smp_processor_id()) )
1168
0
        do_write_psr_msrs(&data);
1169
0
    else
1170
0
    {
1171
0
        unsigned int cpu = get_socket_cpu(socket);
1172
0
1173
0
        if ( cpu >= nr_cpu_ids )
1174
0
            return -ENOTSOCK;
1175
0
        on_selected_cpus(cpumask_of(cpu), do_write_psr_msrs, &data, 1);
1176
0
    }
1177
0
1178
0
    return 0;
1179
0
}
1180
1181
int psr_set_val(struct domain *d, unsigned int socket,
1182
                uint64_t new_val, enum cbm_type type)
1183
0
{
1184
0
    unsigned int old_cos, array_len;
1185
0
    int cos, ret;
1186
0
    unsigned int *ref;
1187
0
    uint32_t *val_array, val;
1188
0
    struct psr_socket_info *info = get_socket_info(socket);
1189
0
    enum psr_feat_type feat_type;
1190
0
1191
0
    if ( IS_ERR(info) )
1192
0
        return PTR_ERR(info);
1193
0
1194
0
    val = new_val;
1195
0
    if ( new_val != val )
1196
0
        return -EINVAL;
1197
0
1198
0
    feat_type = psr_cbm_type_to_feat_type(type);
1199
0
    if ( feat_type >= ARRAY_SIZE(info->features) ||
1200
0
         !info->features[feat_type] )
1201
0
        return -ENOENT;
1202
0
1203
0
    /*
1204
0
     * Step 0:
1205
0
     * old_cos means the COS ID current domain is using. By default, it is 0.
1206
0
     *
1207
0
     * For every COS ID, there is a reference count to record how many domains
1208
0
     * are using the COS register corresponding to this COS ID.
1209
0
     * - If ref[old_cos] is 0, that means this COS is not used by any domain.
1210
0
     * - If ref[old_cos] is 1, that means this COS is only used by current
1211
0
     *   domain.
1212
0
     * - If ref[old_cos] is more than 1, that mean multiple domains are using
1213
0
     *   this COS.
1214
0
     */
1215
0
    domain_lock(d);
1216
0
    if ( !test_and_set_bit(d->domain_id, info->dom_set) )
1217
0
        d->arch.psr_cos_ids[socket] = 0;
1218
0
1219
0
    old_cos = d->arch.psr_cos_ids[socket];
1220
0
    domain_unlock(d);
1221
0
1222
0
    ASSERT(old_cos < MAX_COS_REG_CNT);
1223
0
1224
0
    ref = info->cos_ref;
1225
0
1226
0
    /*
1227
0
     * Step 1:
1228
0
     * Gather a value array to store all features cos_reg_val[old_cos].
1229
0
     * And, set the input new val into array according to the feature's
1230
0
     * position in array.
1231
0
     */
1232
0
    array_len = get_cos_num();
1233
0
    val_array = xzalloc_array(uint32_t, array_len);
1234
0
    if ( !val_array )
1235
0
        return -ENOMEM;
1236
0
1237
0
    if ( (ret = gather_val_array(val_array, array_len, info, old_cos)) != 0 )
1238
0
        goto free_array;
1239
0
1240
0
    if ( (ret = insert_val_into_array(val_array, array_len, info,
1241
0
                                      feat_type, type, val)) != 0 )
1242
0
        goto free_array;
1243
0
1244
0
    spin_lock(&info->ref_lock);
1245
0
1246
0
    /*
1247
0
     * Step 2:
1248
0
     * Try to find if there is already a COS ID on which all features' values
1249
0
     * are same as the array. Then, we can reuse this COS ID.
1250
0
     */
1251
0
    cos = find_cos(val_array, array_len, feat_type, info);
1252
0
    if ( cos == old_cos )
1253
0
    {
1254
0
        ret = 0;
1255
0
        goto unlock_free_array;
1256
0
    }
1257
0
1258
0
    /*
1259
0
     * Step 3:
1260
0
     * If fail to find, we need pick an available COS ID.
1261
0
     * In fact, only COS ID which ref is 1 or 0 can be picked for current
1262
0
     * domain. If old_cos is not 0 and its ref==1, that means only current
1263
0
     * domain is using this old_cos ID. So, this old_cos ID certainly can
1264
0
     * be reused by current domain. Ref==0 means there is no any domain
1265
0
     * using this COS ID. So it can be used for current domain too.
1266
0
     */
1267
0
    if ( cos < 0 )
1268
0
    {
1269
0
        cos = pick_avail_cos(info, val_array, array_len, old_cos, feat_type);
1270
0
        if ( cos < 0 )
1271
0
        {
1272
0
            ret = cos;
1273
0
            goto unlock_free_array;
1274
0
        }
1275
0
1276
0
        /*
1277
0
         * Step 4:
1278
0
         * Write the feature's MSRs according to the COS ID.
1279
0
         */
1280
0
        ret = write_psr_msrs(socket, cos, val_array, array_len, feat_type);
1281
0
        if ( ret )
1282
0
            goto unlock_free_array;
1283
0
    }
1284
0
1285
0
    /*
1286
0
     * Step 5:
1287
0
     * Find the COS ID (find_cos result is '>= 0' or an available COS ID is
1288
0
     * picked, then update ref according to COS ID.
1289
0
     */
1290
0
    ref[cos]++;
1291
0
    ASSERT(!cos || ref[cos]);
1292
0
    ASSERT(!old_cos || ref[old_cos]);
1293
0
    ref[old_cos]--;
1294
0
    spin_unlock(&info->ref_lock);
1295
0
1296
0
    /*
1297
0
     * Step 6:
1298
0
     * Save the COS ID into current domain's psr_cos_ids[] so that we can know
1299
0
     * which COS the domain is using on the socket. One domain can only use
1300
0
     * one COS ID at same time on each socket.
1301
0
     */
1302
0
    domain_lock(d);
1303
0
    d->arch.psr_cos_ids[socket] = cos;
1304
0
    domain_unlock(d);
1305
0
1306
0
    goto free_array;
1307
0
1308
0
 unlock_free_array:
1309
0
    spin_unlock(&info->ref_lock);
1310
0
1311
0
 free_array:
1312
0
    xfree(val_array);
1313
0
    return ret;
1314
0
}
1315
1316
static void psr_free_cos(struct domain *d)
1317
0
{
1318
0
    unsigned int socket, cos;
1319
0
1320
0
    if ( !d->arch.psr_cos_ids )
1321
0
        return;
1322
0
1323
0
    ASSERT(socket_info);
1324
0
1325
0
    /* Domain is destroyed so its cos_ref should be decreased. */
1326
0
    for ( socket = 0; socket < nr_sockets; socket++ )
1327
0
    {
1328
0
        struct psr_socket_info *info = socket_info + socket;
1329
0
1330
0
        clear_bit(d->domain_id, info->dom_set);
1331
0
1332
0
        /* cos 0 is default one which does not need be handled. */
1333
0
        cos = d->arch.psr_cos_ids[socket];
1334
0
        if ( cos == 0 )
1335
0
            continue;
1336
0
1337
0
        spin_lock(&info->ref_lock);
1338
0
        ASSERT(info->cos_ref[cos]);
1339
0
        info->cos_ref[cos]--;
1340
0
        spin_unlock(&info->ref_lock);
1341
0
    }
1342
0
1343
0
    xfree(d->arch.psr_cos_ids);
1344
0
    d->arch.psr_cos_ids = NULL;
1345
0
}
1346
1347
static void psr_alloc_cos(struct domain *d)
1348
0
{
1349
0
    d->arch.psr_cos_ids = xzalloc_array(unsigned int, nr_sockets);
1350
0
    if ( !d->arch.psr_cos_ids )
1351
0
        printk(XENLOG_WARNING "Failed to alloc psr_cos_ids!\n");
1352
0
}
1353
1354
void psr_domain_init(struct domain *d)
1355
2
{
1356
2
    if ( psr_alloc_feat_enabled() )
1357
0
        psr_alloc_cos(d);
1358
2
}
1359
1360
void psr_domain_free(struct domain *d)
1361
0
{
1362
0
    psr_free_rmid(d);
1363
0
    psr_free_cos(d);
1364
0
}
1365
1366
static void __init init_psr(void)
1367
0
{
1368
0
    if ( opt_cos_max < 1 )
1369
0
    {
1370
0
        printk(XENLOG_INFO "CAT: disabled, cos_max is too small\n");
1371
0
        return;
1372
0
    }
1373
0
1374
0
    socket_info = xzalloc_array(struct psr_socket_info, nr_sockets);
1375
0
1376
0
    if ( !socket_info )
1377
0
    {
1378
0
        printk(XENLOG_WARNING "Failed to alloc socket_info!\n");
1379
0
        return;
1380
0
    }
1381
0
}
1382
1383
static void __init psr_free(void)
1384
0
{
1385
0
    xfree(socket_info);
1386
0
    socket_info = NULL;
1387
0
}
1388
1389
static int psr_cpu_prepare(void)
1390
1
{
1391
1
    if ( !psr_alloc_feat_enabled() )
1392
1
        return 0;
1393
1
1394
1
    /* Malloc memory for the global feature node here. */
1395
0
    if ( feat_l3 == NULL &&
1396
0
         (feat_l3 = xzalloc(struct feat_node)) == NULL )
1397
0
        return -ENOMEM;
1398
0
1399
0
    if ( feat_l2_cat == NULL &&
1400
0
         (feat_l2_cat = xzalloc(struct feat_node)) == NULL )
1401
0
        return -ENOMEM;
1402
0
1403
0
    return 0;
1404
0
}
1405
1406
static void psr_cpu_init(void)
1407
1
{
1408
1
    struct psr_socket_info *info;
1409
1
    unsigned int socket, cpu = smp_processor_id();
1410
1
    struct feat_node *feat;
1411
1
    struct cpuid_leaf regs;
1412
1
1413
1
    if ( !psr_alloc_feat_enabled() || !boot_cpu_has(X86_FEATURE_PQE) )
1414
1
        goto assoc_init;
1415
1
1416
0
    if ( boot_cpu_data.cpuid_level < PSR_CPUID_LEVEL_CAT )
1417
0
    {
1418
0
        setup_clear_cpu_cap(X86_FEATURE_PQE);
1419
0
        goto assoc_init;
1420
0
    }
1421
0
1422
0
    socket = cpu_to_socket(cpu);
1423
0
    info = socket_info + socket;
1424
0
    if ( info->feat_init )
1425
0
        goto assoc_init;
1426
0
1427
0
    spin_lock_init(&info->ref_lock);
1428
0
1429
0
    cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 0, &regs);
1430
0
    if ( regs.b & PSR_RESOURCE_TYPE_L3 )
1431
0
    {
1432
0
        cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 1, &regs);
1433
0
1434
0
        feat = feat_l3;
1435
0
        feat_l3 = NULL;
1436
0
1437
0
        if ( (regs.c & PSR_CAT_CDP_CAPABILITY) && (opt_psr & PSR_CDP) &&
1438
0
             !cat_init_feature(&regs, feat, info, FEAT_TYPE_L3_CDP) )
1439
0
            feat_props[FEAT_TYPE_L3_CDP] = &l3_cdp_props;
1440
0
1441
0
        /* If CDP init fails, try to work as L3 CAT. */
1442
0
        if ( !feat_props[FEAT_TYPE_L3_CDP] )
1443
0
        {
1444
0
            if ( !cat_init_feature(&regs, feat, info, FEAT_TYPE_L3_CAT) )
1445
0
                feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props;
1446
0
            else
1447
0
                feat_l3 = feat;
1448
0
        }
1449
0
    }
1450
0
1451
0
    cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 0, &regs);
1452
0
    if ( regs.b & PSR_RESOURCE_TYPE_L2 )
1453
0
    {
1454
0
        cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 2, &regs);
1455
0
1456
0
        feat = feat_l2_cat;
1457
0
        feat_l2_cat = NULL;
1458
0
        if ( !cat_init_feature(&regs, feat, info, FEAT_TYPE_L2_CAT) )
1459
0
            feat_props[FEAT_TYPE_L2_CAT] = &l2_cat_props;
1460
0
        else
1461
0
            feat_l2_cat = feat;
1462
0
    }
1463
0
1464
0
    info->feat_init = true;
1465
0
1466
1
 assoc_init:
1467
1
    psr_assoc_init();
1468
1
}
1469
1470
static void psr_cpu_fini(unsigned int cpu)
1471
0
{
1472
0
    unsigned int socket = cpu_to_socket(cpu);
1473
0
1474
0
    if ( !psr_alloc_feat_enabled() )
1475
0
        return;
1476
0
1477
0
    /*
1478
0
     * We only free when we are the last CPU in the socket. The socket_cpumask
1479
0
     * is cleared prior to this notification code by remove_siblinginfo().
1480
0
     */
1481
0
    if ( socket_cpumask[socket] && cpumask_empty(socket_cpumask[socket]) )
1482
0
        free_socket_resources(socket);
1483
0
}
1484
1485
static int cpu_callback(
1486
    struct notifier_block *nfb, unsigned long action, void *hcpu)
1487
0
{
1488
0
    int rc = 0;
1489
0
    unsigned int cpu = (unsigned long)hcpu;
1490
0
1491
0
    switch ( action )
1492
0
    {
1493
0
    case CPU_UP_PREPARE:
1494
0
        rc = psr_cpu_prepare();
1495
0
        break;
1496
0
    case CPU_STARTING:
1497
0
        psr_cpu_init();
1498
0
        break;
1499
0
    case CPU_UP_CANCELED:
1500
0
    case CPU_DEAD:
1501
0
        psr_cpu_fini(cpu);
1502
0
        break;
1503
0
    }
1504
0
1505
0
    return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
1506
0
}
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
1518
static int __init psr_presmp_init(void)
1519
1
{
1520
1
    if ( (opt_psr & PSR_CMT) && opt_rmid_max )
1521
0
        init_psr_cmt(opt_rmid_max);
1522
1
1523
1
    if ( opt_psr & (PSR_CAT | PSR_CDP) )
1524
0
        init_psr();
1525
1
1526
1
    if ( psr_cpu_prepare() )
1527
0
        psr_free();
1528
1
1529
1
    psr_cpu_init();
1530
1
    if ( psr_cmt_enabled() || psr_alloc_feat_enabled() )
1531
0
        register_cpu_notifier(&cpu_nfb);
1532
1
1533
1
    return 0;
1534
1
}
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
 */