From mboxrd@z Thu Jan 1 00:00:00 1970 From: Chao Peng Subject: [PATCH v8 03/13] x86: maintain COS to CBM mapping for each socket Date: Thu, 21 May 2015 16:41:34 +0800 Message-ID: <1432197704-20816-4-git-send-email-chao.p.peng@linux.intel.com> References: <1432197704-20816-1-git-send-email-chao.p.peng@linux.intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1432197704-20816-1-git-send-email-chao.p.peng@linux.intel.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: keir@xen.org, Ian.Campbell@citrix.com, stefano.stabellini@eu.citrix.com, andrew.cooper3@citrix.com, dario.faggioli@citrix.com, Ian.Jackson@eu.citrix.com, will.auld@intel.com, JBeulich@suse.com, wei.liu2@citrix.com, dgdegra@tycho.nsa.gov List-Id: xen-devel@lists.xenproject.org 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 Reviewed-by: Andrew Cooper --- 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