[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2 3/7] x86: detect and initialize Intel CAT feature



Detect Intel Cache Allocation Technology(CAT) feature and store the
cpuid information for later use. Currently only L3 cache allocation is
supported. The L3 CAT features may vary among sockets so per-socket
feature information is stored. The initialization can happen either at
boot time or when CPU(s) is hot plugged after booting.

Signed-off-by: Chao Peng <chao.p.peng@xxxxxxxxxxxxxxx>
---
Changes in v2:
* socket_num => num_sockets and fix several documentaion issues.
* refactor boot line parameters parsing into standlone patch.
* set opt_num_sockets = NR_CPUS when opt_num_sockets > NR_CPUS.
* replace CPU_ONLINE with CPU_STARTING and integrate that into scheduling
  improvement patch.
* reimplement get_max_socket() with cpu_to_socket();
* cbm is still uint64 as there is a path forward for supporting long masks.
---
 docs/misc/xen-command-line.markdown |  19 ++++++-
 xen/arch/x86/psr.c                  | 105 +++++++++++++++++++++++++++++++++---
 xen/include/asm-x86/cpufeature.h    |   1 +
 3 files changed, 115 insertions(+), 10 deletions(-)

diff --git a/docs/misc/xen-command-line.markdown 
b/docs/misc/xen-command-line.markdown
index 63871cb..768c55f 100644
--- a/docs/misc/xen-command-line.markdown
+++ b/docs/misc/xen-command-line.markdown
@@ -1090,9 +1090,9 @@ This option can be specified more than once (up to 8 
times at present).
 > `= <integer>`
 
 ### psr (Intel)
-> `= List of ( cmt:<boolean> | rmid_max:<integer> )`
+> `= List of ( cmt:<boolean> | rmid_max:<integer> | cat:<boolean> | 
num_sockets:<interger> )`
 
-> Default: `psr=cmt:0,rmid_max:255`
+> Default: `psr=cmt:0,rmid_max:255,cat:0,num_sockets:0(Detect at boot time)`
 
 Platform Shared Resource(PSR) Services.  Intel Haswell and later server
 platforms offer information about the sharing of resources.
@@ -1102,6 +1102,11 @@ Monitoring ID(RMID) is used to bind the domain to 
corresponding shared
 resource.  RMID is a hardware-provided layer of abstraction between software
 and logical processors.
 
+To use the PSR cache allocation service for a certain domain, a capacity
+bitmasks(CBM) is used to bind the domain to corresponding shared resource.
+CBM represents cache capacity and indicates the degree of overlap and isolation
+between domains.
+
 The following resources are available:
 
 * Cache Monitoring Technology (Haswell and later).  Information regarding the
@@ -1112,6 +1117,16 @@ The following resources are available:
   total/local memory bandwidth. Follow the same options with Cache Monitoring
   Technology.
 
+* Cache Alllocation Technology (Broadwell and later).  Information regarding
+  the cache allocation.
+  * `cat` instructs Xen to enable/disable Cache Allocation Technology.
+  * `num_sockets` indicates the number of available sockets for CAT feature
+    detection. All the sockets up to num_sockets will be checked for CAT
+    feature. The value is normally detected at boot time automatically if not
+    specified(0). While the value may need to be specified manually for CPU
+    hot-plug scenario in which case the automatic sockets number detection may
+    be not correct.
+
 ### reboot
 > `= t[riple] | k[bd] | a[cpi] | p[ci] | n[o] [, [w]arm | [c]old]`
 
diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
index 015bc07..5946122 100644
--- a/xen/arch/x86/psr.c
+++ b/xen/arch/x86/psr.c
@@ -19,17 +19,39 @@
 #include <asm/psr.h>
 
 #define PSR_CMT        (1<<0)
+#define PSR_CAT        (1<<1)
+
+struct psr_cat_socket_info {
+    bool_t initialized;
+    bool_t enabled;
+    unsigned int cbm_len;
+    unsigned int cos_max;
+};
 
 struct psr_assoc {
     uint64_t val;
 };
 
 struct psr_cmt *__read_mostly psr_cmt;
+static struct psr_cat_socket_info *__read_mostly cat_socket_info;
+
 static unsigned int __initdata opt_psr;
 static unsigned int __initdata opt_rmid_max = 255;
+static unsigned int __read_mostly opt_num_sockets;
 static uint64_t rmid_mask;
 static DEFINE_PER_CPU(struct psr_assoc, psr_assoc);
 
+static unsigned int get_max_socket(void)
+{
+    unsigned int cpu, socket = 0;
+
+    for_each_present_cpu(cpu)
+        if ( socket < cpu_to_socket(cpu) )
+            socket = cpu_to_socket(cpu);
+
+    return socket;
+}
+
 static void __init parse_psr_bool(char* s, char* value, char* feature, int bit)
 {
     if ( !strcmp(s, feature) )
@@ -62,8 +84,15 @@ static void __init parse_psr_param(char *s)
             *val_str++ = '\0';
 
         parse_psr_bool(s, val_str, "cmt", PSR_CMT);
-        if ( val_str && !strcmp(s, "rmid_max") )
-            opt_rmid_max = simple_strtoul(val_str, NULL, 0);
+        parse_psr_bool(s, val_str, "cat", PSR_CAT);
+
+        if ( val_str )
+        {
+            if ( !strcmp(s, "rmid_max") )
+                opt_rmid_max = simple_strtoul(val_str, NULL, 0);
+            else if ( !strcmp(s, "num_sockets") )
+                opt_num_sockets = simple_strtoul(val_str, NULL, 0);
+        }
 
         s = ss + 1;
     } while ( ss );
@@ -204,9 +233,66 @@ void psr_ctxt_switch_to(struct domain *d)
     psr_assoc_reg_write(psra, reg);
 }
 
+static void cat_cpu_init(unsigned int cpu)
+{
+    unsigned int eax, ebx, ecx, edx;
+    struct psr_cat_socket_info *info;
+    unsigned int socket;
+    const struct cpuinfo_x86 *c;
+
+    socket = cpu_to_socket(cpu);
+    if ( socket >= opt_num_sockets )
+    {
+        printk(XENLOG_WARNING "CAT: disabled on socket %d as num_sockets is 
%d\n",
+               socket, opt_num_sockets);
+        return;
+    }
+
+    info = cat_socket_info + socket;
+
+    /* Avoid initializing more than one times for the same socket. */
+    if ( test_and_set_bool(info->initialized) )
+        return;
+
+    c = cpu_data + cpu;
+    if ( !cpu_has(c, X86_FEATURE_CAT) )
+        return;
+
+    cpuid_count(0x10, 0, &eax, &ebx, &ecx, &edx);
+    if ( ebx & PSR_RESOURCE_TYPE_L3 )
+    {
+        cpuid_count(0x10, 1, &eax, &ebx, &ecx, &edx);
+        info->cbm_len = (eax & 0x1f) + 1;
+        info->cos_max = (edx & 0xffff);
+
+        info->enabled = 1;
+        printk(XENLOG_DEBUG "CAT: enabled on socket %u, cos_max:%u, 
cbm_len:%u\n",
+               socket, info->cos_max, info->cbm_len);
+    }
+}
+
+static void __init init_psr_cat(void)
+{
+    if ( opt_num_sockets == 0 )
+        opt_num_sockets = get_max_socket() + 1;
+    else if ( opt_num_sockets > NR_CPUS )
+    {
+        opt_num_sockets = NR_CPUS;
+        printk(XENLOG_WARNING "num_sockets > NR_CPUS(%d), set to NR_CPUS\n",
+                NR_CPUS);
+    }
+
+    cat_socket_info = xzalloc_array(struct psr_cat_socket_info,
+                                    opt_num_sockets);
+}
+
 static void psr_cpu_init(unsigned int cpu)
 {
-    psr_assoc_init();
+    if ( cat_socket_info )
+        cat_cpu_init(cpu);
+
+    if (  psr_cmt_enabled() )
+        psr_assoc_init();
 }
 
 static int cpu_callback(
@@ -233,14 +319,17 @@ static int __init psr_presmp_init(void)
     if ( (opt_psr & PSR_CMT) && opt_rmid_max )
         init_psr_cmt(opt_rmid_max);
 
-    if (  psr_cmt_enabled() )
-    {
-        psr_cpu_init(smp_processor_id());
-        register_cpu_notifier(&cpu_nfb);
-    }
+    if ( opt_psr & PSR_CAT )
+        init_psr_cat();
+
+    psr_cpu_init(smp_processor_id());
+
+    if ( psr_cmt_enabled() || cat_socket_info )
+          register_cpu_notifier(&cpu_nfb);
 
     return 0;
 }
+
 presmp_initcall(psr_presmp_init);
 
 /*
diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h
index 7963a3a..8c0f0a6 100644
--- a/xen/include/asm-x86/cpufeature.h
+++ b/xen/include/asm-x86/cpufeature.h
@@ -149,6 +149,7 @@
 #define X86_FEATURE_CMT        (7*32+12) /* Cache Monitoring Technology */
 #define X86_FEATURE_NO_FPU_SEL         (7*32+13) /* FPU CS/DS stored as zero */
 #define X86_FEATURE_MPX                (7*32+14) /* Memory Protection 
Extensions */
+#define X86_FEATURE_CAT        (7*32+15) /* Cache Allocation Technology */
 #define X86_FEATURE_RDSEED     (7*32+18) /* RDSEED instruction */
 #define X86_FEATURE_ADX                (7*32+19) /* ADCX, ADOX instructions */
 #define X86_FEATURE_SMAP       (7*32+20) /* Supervisor Mode Access Prevention 
*/
-- 
1.9.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.