For each socket, a COS to CBM mapping structure is maintained for each
COS. The mapping is indexed by COS and the value is the corresponding
CBM. Different VMs may use the same CBM, a reference count is used to
indicate if the CBM is available.

Signed-off-by: Chao Peng <chao.p.p...@linux.intel.com>
Reviewed-by: Andrew Cooper <andrew.coop...@citrix.com>
---
Changes in v8:
* Move the memory allocation and CAT initialization code to CPU_UP_PREPARE.
* Add memory freeing code in CPU_DEAD path.
Changes in v5:
* rename cos_cbm_map to cos_to_cbm.
---
 xen/arch/x86/psr.c | 98 +++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 78 insertions(+), 20 deletions(-)

diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
index 471296e..8c844cb 100644
--- a/xen/arch/x86/psr.c
+++ b/xen/arch/x86/psr.c
@@ -21,9 +21,15 @@
 #define PSR_CMT        (1<<0)
 #define PSR_CAT        (1<<1)
 
+struct psr_cat_cbm {
+    uint64_t cbm;
+    unsigned int ref;
+};
+
 struct psr_cat_socket_info {
     unsigned int cbm_len;
     unsigned int cos_max;
+    struct psr_cat_cbm *cos_to_cbm;
 };
 
 struct psr_assoc {
@@ -208,34 +214,62 @@ void psr_ctxt_switch_to(struct domain *d)
         psra->val = reg;
     }
 }
-
-static void cat_cpu_init(void)
+static void do_cat_cpu_init(void *arg)
 {
     unsigned int eax, ebx, ecx, edx;
-    struct psr_cat_socket_info *info;
-    unsigned int socket;
-    unsigned int cpu = smp_processor_id();
-    const struct cpuinfo_x86 *c = cpu_data + cpu;
-
-    if ( !cpu_has(c, X86_FEATURE_CAT) )
-        return;
-
-    socket = cpu_to_socket(cpu);
-    if ( test_bit(socket, cat_socket_enable) )
-        return;
+    int *rc = arg;
 
     cpuid_count(PSR_CPUID_LEVEL_CAT, 0, &eax, &ebx, &ecx, &edx);
     if ( ebx & PSR_RESOURCE_TYPE_L3 )
     {
+        struct psr_cat_socket_info *info;
+        unsigned int socket = cpu_to_socket(smp_processor_id());
+
         cpuid_count(PSR_CPUID_LEVEL_CAT, 1, &eax, &ebx, &ecx, &edx);
         info = cat_socket_info + socket;
         info->cbm_len = (eax & 0x1f) + 1;
         info->cos_max = min(opt_cos_max, edx & 0xffff);
 
+        info->cos_to_cbm = xzalloc_array(struct psr_cat_cbm,
+                                         info->cos_max + 1UL);
+        if ( !info->cos_to_cbm )
+        {
+            *rc = -ENOMEM;
+            return;
+        }
+
+        /* cos=0 is reserved as default cbm(all ones). */
+        info->cos_to_cbm[0].cbm = (1ull << info->cbm_len) - 1;
+
         set_bit(socket, cat_socket_enable);
         printk(XENLOG_INFO "CAT: enabled on socket %u, cos_max:%u, 
cbm_len:%u\n",
                socket, info->cos_max, info->cbm_len);
     }
+
+    *rc = 0;
+
+    return;
+
+}
+
+
+static int cat_cpu_init(unsigned int cpu)
+{
+    int rc;
+    const struct cpuinfo_x86 *c = cpu_data + cpu;
+
+    if ( !cpu_has(c, X86_FEATURE_CAT) )
+        return 0;
+
+    if ( test_bit(cpu_to_socket(cpu), cat_socket_enable) )
+        return 0;
+
+    if ( cpu == smp_processor_id() )
+        do_cat_cpu_init(&rc);
+    else
+        on_selected_cpus(cpumask_of(cpu), do_cat_cpu_init, &rc, 1);
+
+    return rc;
 }
 
 static void cat_cpu_fini(unsigned int cpu)
@@ -243,7 +277,16 @@ static void cat_cpu_fini(unsigned int cpu)
     unsigned int socket = cpu_to_socket(cpu);
 
     if ( !socket_cpumask[socket] || cpumask_empty(socket_cpumask[socket]) )
+    {
+        struct psr_cat_socket_info *info = cat_socket_info + socket;
+
+        if ( info->cos_to_cbm )
+        {
+            xfree(info->cos_to_cbm);
+            info->cos_to_cbm = NULL;
+        }
         clear_bit(socket, cat_socket_enable);
+    }
 }
 
 static void __init init_psr_cat(void)
@@ -266,11 +309,16 @@ static void __init init_psr_cat(void)
     }
 }
 
-static void psr_cpu_init(void)
+static int psr_cpu_prepare(unsigned int cpu)
 {
     if ( cat_socket_info )
-        cat_cpu_init();
+        return cat_cpu_init(cpu);
 
+    return 0;
+}
+
+static void psr_cpu_starting(void)
+{
     psr_assoc_init();
 }
 
@@ -283,14 +331,24 @@ static void psr_cpu_fini(unsigned int cpu)
 static int cpu_callback(
     struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
+    int rc = 0;
     unsigned int cpu = (unsigned long)hcpu;
 
-    if ( action == CPU_STARTING )
-        psr_cpu_init();
-    else if ( action == CPU_DEAD )
+    switch ( action )
+    {
+    case CPU_UP_PREPARE:
+        rc = psr_cpu_prepare(cpu);
+        break;
+    case CPU_STARTING:
+        psr_cpu_starting();
+        break;
+    case CPU_UP_CANCELED:
+    case CPU_DEAD:
         psr_cpu_fini(cpu);
+        break;
+    }
 
-    return NOTIFY_DONE;
+    return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
 }
 
 static struct notifier_block cpu_nfb = {
@@ -305,7 +363,7 @@ static int __init psr_presmp_init(void)
     if ( opt_psr & PSR_CAT )
         init_psr_cat();
 
-    psr_cpu_init();
+    psr_cpu_prepare(0);
     if ( psr_cmt_enabled() || cat_socket_info )
         register_cpu_notifier(&cpu_nfb);
 
-- 
1.9.1


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

Reply via email to