Skip to content

Commit d0665fe

Browse files
vijaydhanrajwenlingz
authored andcommitted
HV: Generalize RDT infrastructure and fix RDT
cache configuration. This patch creates a generic infrastructure for RDT resources instead of just L2 or L3 cache. This patch also fixes L3 CAT config overwrite by L2 in cases where both L2 and L3 CAT are supported. Tracked-On: #3715 Signed-off-by: Vijay Dhanraj <vijay.dhanraj@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent 887e381 commit d0665fe

File tree

6 files changed

+145
-68
lines changed

6 files changed

+145
-68
lines changed

hypervisor/arch/x86/Kconfig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,12 @@ config HYPERV_ENABLED
261261
When set, the minimum set of TLFS functionality together with some
262262
performance enlightenments are enabled.
263263

264-
config CAT_ENABLED
265-
bool "Enable CAT (Cache Allocation Technology)"
264+
config RDT_ENABLED
265+
bool "Enable RDT (Resource Director Technology)"
266266
default n
267267
help
268-
When set in platforms that support CAT, hypervisor can allocate
269-
various amount of last-level-cache (LLC) resources to VMs to achieve
268+
When set in platforms that support RDT, hypervisor can allocate
269+
various amount of HW resources such as L2 or/and L3 to VMs to achieve
270270
different Class of Service (COS, or CLOS).
271271

272272
config GPU_SBDF

hypervisor/arch/x86/cpu.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,10 @@ void init_pcpu_pre(bool is_bsp)
153153
panic("System IOAPIC info is incorrect!");
154154
}
155155

156-
#ifdef CONFIG_CAT_ENABLED
157-
ret = init_cat_cap_info();
156+
#ifdef CONFIG_RDT_ENABLED
157+
ret = init_rdt_cap_info();
158158
if (ret != 0) {
159-
panic("Platform CAT info is incorrect!");
159+
panic("Platform RDT info is incorrect!");
160160
}
161161
#endif
162162

@@ -262,7 +262,9 @@ void init_pcpu_post(uint16_t pcpu_id)
262262

263263
init_sched(pcpu_id);
264264

265-
setup_clos(pcpu_id);
265+
if (!setup_clos(pcpu_id)) {
266+
panic("CLOS resource MSRs setup incorrectly!");
267+
}
266268

267269
enable_smep();
268270

hypervisor/arch/x86/rdt.c

Lines changed: 113 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -12,79 +12,141 @@
1212
#include <errno.h>
1313
#include <logmsg.h>
1414
#include <rdt.h>
15+
#include <bits.h>
1516
#include <board.h>
1617
#include <vm_config.h>
1718
#include <msr.h>
1819

19-
struct cat_hw_info cat_cap_info = {false, 0U, 0U, 0U, 0U};
20+
static struct rdt_info res_cap_info[RDT_NUM_RESOURCES] = {
21+
[RDT_RESOURCE_L3] = {
22+
.bitmask = 0U,
23+
.cbm_len = 0U,
24+
.clos_max = 0U,
25+
.res_id = RDT_RESID_L3,
26+
.msr_base = MSR_IA32_L3_MASK_BASE,
27+
.platform_clos_array = NULL
28+
},
29+
[RDT_RESOURCE_L2] = {
30+
.bitmask = 0U,
31+
.cbm_len = 0U,
32+
.clos_max = 0U,
33+
.res_id = RDT_RESID_L2,
34+
.msr_base = MSR_IA32_L2_MASK_BASE,
35+
.platform_clos_array = NULL
36+
},
37+
};
2038
const uint16_t hv_clos = 0U;
21-
uint16_t platform_clos_num = MAX_PLATFORM_CLOS_NUM;
39+
/* RDT features can support different numbers of CLOS. Set the lowers numerical
40+
* clos value (platform_clos_num) that is common between the resources as
41+
* each resource's clos max value to have consistent allocation.
42+
*/
43+
const uint16_t platform_clos_num = MAX_PLATFORM_CLOS_NUM;
44+
45+
static void rdt_read_cat_capability(int res)
46+
{
47+
uint32_t eax = 0U, ebx = 0U, ecx = 0U, edx = 0U;
2248

23-
int32_t init_cat_cap_info(void)
49+
/* CPUID.(EAX=0x10,ECX=ResID):EAX[4:0] reports the length of CBM supported
50+
* CPUID.(EAX=0x10,ECX=ResID):EBX[31:0] indicates shared cache mask bits
51+
* that are used by other entities such as graphic and H/W outside processor.
52+
* CPUID.(EAX=0x10,ECX=ResID):EDX[15:0] reports the maximun CLOS supported
53+
*/
54+
cpuid_subleaf(CPUID_RDT_ALLOCATION, res_cap_info[res].res_id, &eax, &ebx, &ecx, &edx);
55+
res_cap_info[res].cbm_len = (uint16_t)((eax & 0xfU) + 1U);
56+
res_cap_info[res].bitmask = ebx;
57+
res_cap_info[res].clos_max = (uint16_t)(edx & 0xffffU) + 1;
58+
}
59+
60+
int32_t init_rdt_cap_info(void)
2461
{
62+
uint8_t i;
2563
uint32_t eax = 0U, ebx = 0U, ecx = 0U, edx = 0U;
2664
int32_t ret = 0;
2765

28-
if (pcpu_has_cap(X86_FEATURE_CAT)) {
29-
cpuid_subleaf(CPUID_RSD_ALLOCATION, 0, &eax, &ebx, &ecx, &edx);
30-
/* If support L3 CAT, EBX[1] is set */
66+
if (pcpu_has_cap(X86_FEATURE_RDT_A)) {
67+
cpuid_subleaf(CPUID_RDT_ALLOCATION, 0, &eax, &ebx, &ecx, &edx);
68+
69+
/* If HW supports L3 CAT, EBX[1] is set */
3170
if ((ebx & 2U) != 0U) {
32-
cat_cap_info.enabled = true;
33-
cat_cap_info.res_id = CAT_RESID_L3;
71+
rdt_read_cat_capability(RDT_RESOURCE_L3);
3472
}
3573

36-
/* If support L2 CAT, EBX[2] is set */
74+
/* If HW supports L2 CAT, EBX[2] is set */
3775
if ((ebx & 4U) != 0U) {
38-
cat_cap_info.enabled = true;
39-
cat_cap_info.res_id = CAT_RESID_L2;
76+
rdt_read_cat_capability(RDT_RESOURCE_L2);
4077
}
4178

42-
/* CPUID.(EAX=0x10,ECX=ResID):EAX[4:0] reports the length of CBM supported
43-
* CPUID.(EAX=0x10,ECX=ResID):EBX[31:0] indicates the corresponding uints
44-
* may be used by other entities such as graphic and H/W outside processor.
45-
* CPUID.(EAX=0x10,ECX=ResID):EDX[15:0] reports the maximun CLOS supported
46-
*/
47-
cpuid_subleaf(CPUID_RSD_ALLOCATION, cat_cap_info.res_id, &eax, &ebx, &ecx, &edx);
48-
cat_cap_info.cbm_len = (uint16_t)((eax & 0x1fU) + 1U);
49-
cat_cap_info.bitmask = ebx;
50-
cat_cap_info.clos_max = (uint16_t)(edx & 0xffffU);
51-
52-
if ((platform_clos_num != 0U) && ((cat_cap_info.clos_max + 1U) != platform_clos_num)) {
53-
pr_err("%s clos_max:%hu, platform_clos_num:%u\n",
54-
__func__, cat_cap_info.clos_max, platform_clos_num);
55-
ret = -EINVAL;
79+
for (i = 0U; i < RDT_NUM_RESOURCES; i++) {
80+
/* If clos_max == 0, the resource is not supported
81+
* so skip checking and updating the clos_max
82+
*/
83+
if (res_cap_info[i].clos_max > 0U) {
84+
if ((platform_clos_num == 0U) || (res_cap_info[i].clos_max < platform_clos_num)) {
85+
pr_err("Invalid Res_ID %d clos max:platform_clos_max=%d, res_clos_max=%d\n",
86+
res_cap_info[i].res_id, platform_clos_num, res_cap_info[i].clos_max);
87+
ret = -EINVAL;
88+
break;
89+
}
90+
/*Store user configured platform clos mask and MSR in the rdt_info struct*/
91+
if (res_cap_info[i].res_id == RDT_RESID_L3) {
92+
res_cap_info[i].platform_clos_array = platform_l3_clos_array;
93+
} else if (res_cap_info[i].res_id == RDT_RESID_L2) {
94+
res_cap_info[i].platform_clos_array = platform_l2_clos_array;
95+
} else {
96+
res_cap_info[i].platform_clos_array = NULL;
97+
}
98+
}
5699
}
57100
}
58-
59101
return ret;
60102
}
61103

62-
void setup_clos(uint16_t pcpu_id)
104+
static bool setup_res_clos_msr(uint16_t pcpu_id, struct platform_clos_info *res_clos_info)
63105
{
106+
bool ret = true;
64107
uint16_t i;
65108
uint32_t msr_index;
66109
uint64_t val;
67110

68-
if (cat_cap_info.enabled) {
69-
for (i = 0; i < platform_clos_num; i++) {
70-
switch (cat_cap_info.res_id) {
71-
case CAT_RESID_L2:
72-
msr_index = platform_l2_clos_array[i].msr_index;
73-
val = (uint64_t)platform_l2_clos_array[i].clos_mask;
74-
msr_write_pcpu(msr_index, val, pcpu_id);
75-
break;
76-
case CAT_RESID_L3:
77-
msr_index = platform_l3_clos_array[i].msr_index;
78-
val = (uint64_t)platform_l3_clos_array[i].clos_mask;
79-
msr_write_pcpu(msr_index, val, pcpu_id);
111+
for (i = 0; i < platform_clos_num; i++) {
112+
if ((fls32(res_clos_info->clos_mask) >= res_cap_info->cbm_len) ||
113+
(res_clos_info->msr_index != (res_cap_info->msr_base + i))) {
114+
ret = false;
115+
pr_err("Incorrect CLOS %d Mask=0x%x and(/or) MSR index=0x%x for Res_ID %d in board.c",
116+
i, res_clos_info->clos_mask, res_clos_info->msr_index, res_cap_info[i].res_id);
117+
break;
118+
}
119+
msr_index = res_clos_info->msr_index;
120+
val = (uint64_t)res_clos_info->clos_mask;
121+
msr_write_pcpu(msr_index, val, pcpu_id);
122+
res_clos_info++;
123+
}
124+
125+
return ret;
126+
}
127+
128+
bool setup_clos(uint16_t pcpu_id)
129+
{
130+
bool ret = true;
131+
uint16_t i;
132+
133+
for (i = 0U; i < RDT_NUM_RESOURCES; i++) {
134+
/* If clos_max == 0, the resource is not supported
135+
* so skip setting up resource MSR.
136+
*/
137+
if (res_cap_info[i].clos_max > 0U) {
138+
ret = setup_res_clos_msr(pcpu_id, res_cap_info[i].platform_clos_array);
139+
if (!ret)
80140
break;
81-
default:
82-
pr_err("Invalid RDT resource configuration\n");
83-
}
84141
}
85-
/* set hypervisor CAT clos */
142+
}
143+
144+
if (ret) {
145+
/* set hypervisor RDT resource clos */
86146
msr_write_pcpu(MSR_IA32_PQR_ASSOC, clos2pqr_msr(hv_clos), pcpu_id);
87147
}
148+
149+
return ret;
88150
}
89151

90152
uint64_t clos2pqr_msr(uint16_t clos)
@@ -99,5 +161,12 @@ uint64_t clos2pqr_msr(uint16_t clos)
99161

100162
bool is_platform_rdt_capable(void)
101163
{
102-
return cat_cap_info.enabled;
164+
bool ret = false;
165+
166+
if ((res_cap_info[RDT_RESOURCE_L3].clos_max > 0U) ||
167+
(res_cap_info[RDT_RESOURCE_L2].clos_max > 0U)) {
168+
ret = true;
169+
}
170+
171+
return ret;
103172
}

hypervisor/include/arch/x86/cpufeatures.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
#define X86_FEATURE_SMEP ((FEAT_7_0_EBX << 5U) + 7U)
7575
#define X86_FEATURE_ERMS ((FEAT_7_0_EBX << 5U) + 9U)
7676
#define X86_FEATURE_INVPCID ((FEAT_7_0_EBX << 5U) + 10U)
77-
#define X86_FEATURE_CAT ((FEAT_7_0_EBX << 5U) + 15U)
77+
#define X86_FEATURE_RDT_A ((FEAT_7_0_EBX << 5U) + 15U)
7878
#define X86_FEATURE_SMAP ((FEAT_7_0_EBX << 5U) + 20U)
7979
#define X86_FEATURE_CLFLUSHOPT ((FEAT_7_0_EBX << 5U) + 23U)
8080

hypervisor/include/arch/x86/cpuid.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
#define CPUID_SERIALNUM 3U
115115
#define CPUID_EXTEND_FEATURE 7U
116116
#define CPUID_XSAVE_FEATURES 0xDU
117-
#define CPUID_RSD_ALLOCATION 0x10U
117+
#define CPUID_RDT_ALLOCATION 0x10U
118118
#define CPUID_MAX_EXTENDED_FUNCTION 0x80000000U
119119
#define CPUID_EXTEND_FUNCTION_1 0x80000001U
120120
#define CPUID_EXTEND_FUNCTION_2 0x80000002U

hypervisor/include/arch/x86/rdt.h

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,32 @@
77
#ifndef RDT_H
88
#define RDT_H
99

10-
/* The intel Resource Director Tech(RDT) based Cache Allocation Tech support */
11-
struct cat_hw_info {
12-
bool enabled; /* If L2/L3 CAT enabled */
13-
uint32_t bitmask; /* Used by other entities */
14-
uint16_t cbm_len; /* Length of Cache mask in bits */
15-
uint16_t clos_max; /* Maximum CLOS supported, the number of cache masks */
10+
enum {
11+
RDT_RESOURCE_L3,
12+
RDT_RESOURCE_L2,
1613

17-
uint32_t res_id;
14+
/* Must be the last */
15+
RDT_NUM_RESOURCES,
1816
};
1917

20-
extern struct cat_hw_info cat_cap_info;
21-
extern const uint16_t hv_clos;
22-
extern uint16_t platform_clos_num;
23-
void setup_clos(uint16_t pcpu_id);
18+
#define RDT_RESID_L3 1U
19+
#define RDT_RESID_L2 2U
2420

21+
extern const uint16_t hv_clos;
22+
extern const uint16_t platform_clos_num;
2523

26-
#define CAT_RESID_L3 1U
27-
#define CAT_RESID_L2 2U
24+
/* The intel Resource Director Tech(RDT) based Allocation Tech support */
25+
struct rdt_info {
26+
uint32_t bitmask; /* Shared CLOS bitmask used by other entities */
27+
uint16_t cbm_len; /* Length of Cache mask in bits */
28+
uint16_t clos_max; /* Maximum CLOS supported, 0 indicates resource is not supported.*/
29+
uint32_t res_id;
30+
uint32_t msr_base; /* MSR base to program clos mask*/
31+
struct platform_clos_info *platform_clos_array; /* user configured mask and MSR info for each CLOS*/
32+
};
2833

29-
int32_t init_cat_cap_info(void);
34+
int32_t init_rdt_cap_info(void);
35+
bool setup_clos(uint16_t pcpu_id);
3036
uint64_t clos2pqr_msr(uint16_t clos);
3137
bool is_platform_rdt_capable(void);
3238

0 commit comments

Comments
 (0)