From patchwork Sat Jul 15 00:31:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi Sun X-Patchwork-Id: 9841853 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3006C60212 for ; Sat, 15 Jul 2017 00:48:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1ED8928798 for ; Sat, 15 Jul 2017 00:48:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 138E9287B3; Sat, 15 Jul 2017 00:48:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B732928798 for ; Sat, 15 Jul 2017 00:48:52 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dWBDn-000780-0q; Sat, 15 Jul 2017 00:46:11 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dWBDl-000755-E8 for xen-devel@lists.xenproject.org; Sat, 15 Jul 2017 00:46:09 +0000 Received: from [85.158.137.68] by server-3.bemta-3.messagelabs.com id A8/AA-01987-BC569695; Sat, 15 Jul 2017 00:46:03 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFuplkeJIrShJLcpLzFFi42I5YG6irXsqNTP SYMEUPYvvWyYzOTB6HP5whSWAMYo1My8pvyKBNWP7jjesBRvOMVY8+z2XsYHx1AzGLkZODiGB CokHE1+zgdgSArwSR5bNYIWw/SUW/P7KClHTwCjxbYcDiM0moC7x+GsPE4gtIqAkcW/VZCCbi 4NZYD6TxOvzD5hBEsICeRLrJ28FK2IRUJW4N3cTWJxXwF3i6YI5TBAL5CROHpsMtoBTwENi6r 429i5GDqBl7hIts8snMPIuYGRYxahRnFpUllqka2ygl1SUmZ5RkpuYmaNraGCsl5taXJyYnpq TmFSsl5yfu4kRGBD1DAyMOxg7T/gdYpTkYFIS5X13OyNSiC8pP6UyI7E4I76oNCe1+BCjDAeH kgTv1JTMSCHBotT01Iq0zBxgaMKkJTh4lER4Z4GkeYsLEnOLM9MhUqcY7Tk2rF7/hYnjTt8GI Plqwv9vTBxN3z9+ZxJiycvPS5US59UEaRMAacsozYMbCoulS4yyUsK8jAwMDEI8BalFuZklqP KvGMU5GJWEeeeDTOHJzCuB2/0K6CwmoLPasjJAzipJREhJNTDmNNxm0G1gjkheevW1/6FPn41 uSJtwsCdsmFasziZ0Vud42cbk40uK72R52FQ1GNWt6D9ywNv2tpjolbUFb0zv7DISN9ZQqbE+ oyxbeGsbW3Si70K/eewmoi+3uC+X2m74M8PDMowp5aH+99XqBbeji8ozi5mW25ssui9sFvjrV prNqiNZ35RYijMSDbWYi4oTAdVIs1CgAgAA X-Env-Sender: yi.y.sun@linux.intel.com X-Msg-Ref: server-6.tower-31.messagelabs.com!1500079549!66978060!5 X-Originating-IP: [192.55.52.43] X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG X-StarScan-Received: X-StarScan-Version: 9.4.25; banners=-,-,- X-VirusChecked: Checked Received: (qmail 21748 invoked from network); 15 Jul 2017 00:46:02 -0000 Received: from mga05.intel.com (HELO mga05.intel.com) (192.55.52.43) by server-6.tower-31.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 15 Jul 2017 00:46:02 -0000 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga105.fm.intel.com with ESMTP; 14 Jul 2017 17:46:01 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.40,360,1496127600"; d="scan'208";a="111534770" Received: from vmmmba-s2600wft.bj.intel.com ([10.240.193.80]) by orsmga002.jf.intel.com with ESMTP; 14 Jul 2017 17:45:58 -0700 From: Yi Sun To: xen-devel@lists.xenproject.org Date: Sat, 15 Jul 2017 08:31:37 +0800 Message-Id: <1500078716-5928-5-git-send-email-yi.y.sun@linux.intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1500078716-5928-1-git-send-email-yi.y.sun@linux.intel.com> References: <1500078716-5928-1-git-send-email-yi.y.sun@linux.intel.com> Cc: kevin.tian@intel.com, wei.liu2@citrix.com, andrew.cooper3@citrix.com, dario.faggioli@citrix.com, ian.jackson@eu.citrix.com, Yi Sun , mengxu@cis.upenn.edu, jbeulich@suse.com, chao.p.peng@linux.intel.com, roger.pau@citrix.com Subject: [Xen-devel] [PATCH v14 04/23] x86: refactor psr: L3 CAT: implement main data structures, CPU init and free flows. X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP To construct an extendible framework, we need analyze PSR features and abstract the common things and feature specific things. Then, encapsulate them into different data structures. By analyzing PSR features, we can get below map. +------+------+------+ --------->| Dom0 | Dom1 | ... | | +------+------+------+ | | |Dom ID | cos_id of domain | V | +-----------------------------------------------------------------------------+ User --------->| PSR | Socket ID | +--------------+---------------+---------------+ | | | Socket0 Info | Socket 1 Info | ... | | | +--------------+---------------+---------------+ | | | cos_id=0 cos_id=1 ... | | | +-----------------------+-----------------------+-----------+ | | |->Ref : | ref 0 | ref 1 | ... | | | | +-----------------------+-----------------------+-----------+ | | | +-----------------------+-----------------------+-----------+ | | |->L3 CAT: | cos 0 | cos 1 | ... | | | | +-----------------------+-----------------------+-----------+ | | | +-----------------------+-----------------------+-----------+ | | |->L2 CAT: | cos 0 | cos 1 | ... | | | | +-----------------------+-----------------------+-----------+ | | | +-----------+-----------+-----------+-----------+-----------+ | | |->CDP : | cos0 code | cos0 data | cos1 code | cos1 data | ... | | | +-----------+-----------+-----------+-----------+-----------+ | +-----------------------------------------------------------------------------+ So, we need define a socket info data structure, 'struct psr_socket_info' to manage information per socket. It contains a reference count array according to COS ID and a feature array to manage all features enabled. Every entry of the reference count array is used to record how many domains are using the COS registers according to the COS ID. For example, L3 CAT and L2 CAT are enabled, Dom1 uses COS_ID=1 registers of both features to save CBM values, like below. +-------+-------+-------+-----+ | COS 0 | COS 1 | COS 2 | ... | +-------+-------+-------+-----+ L3 CAT | 0x7ff | 0x1ff | ... | ... | +-------+-------+-------+-----+ L2 CAT | 0xff | 0xff | ... | ... | +-------+-------+-------+-----+ If Dom2 has same CBM values, it can reuse these registers which COS_ID=1. That means, both Dom1 and Dom2 use same COS registers(ID=1) to keep same L3/L2 values. So, the value of ref[1] is 2 which means 2 domains are using COS_ID 1. To manage a feature, we need define a feature node data structure, 'struct feat_node', to manage feature's specific HW info, and an array of all COS registers values of this feature. To manage feature properties, we need define a feature property data structure, 'struct feat_props', to manage common properties (callback functions - all feature's specific behaviors are encapsulated into these callback functions, and generic values - e.g. the cos_max), the feature independent values. CDP is a special feature which uses two entries of the array for one COS ID. So, the number of CDP COS registers is the half of L3 CAT. E.g. L3 CAT has 16 COS registers, then CDP has 8 COS registers if it is enabled. CDP uses the COS registers array as below. +-----------+-----------+-----------+-----------+-----------+ CDP cos_reg_val[] index: | 0 | 1 | 2 | 3 | ... | +-----------+-----------+-----------+-----------+-----------+ value: | cos0 code | cos0 data | cos1 code | cos1 data | ... | +-----------+-----------+-----------+-----------+-----------+ For more details, please refer SDM and patches to implement 'get value' and 'set value'. This patch also implements the CPU init and free flow including L3 CAT initialization and some resources free. It includes below flows: 1. presmp init: - parse command line parameter. - allocate socket info for every socket. - allocate feature resource. - initialize socket info, get feature info and add feature into feature array per cpuid result. - free resources allocated if error happens. - register cpu notifier to handle cpu events. 2. cpu notifier: - handle cpu online events, if initialization work has been done before, do nothing. - handle cpu offline events, if it is the last cpu offline, free some socket resources. Signed-off-by: Yi Sun Reviewed-by: Jan Beulich --- v14: - rename 'feat_l3_cat' to 'feat_l3' to represent for either L3 CAT or CDP. Because only one of them can exist at same time. (suggested by Jan Beulich) - put address of 'feat_l3' back into it if 'cat_init_feature()' fails to avoid leakage. (suggested by Jan Beulich) v13: - modify macros and enum identifiers names to be consistent. (suggested by Jan Beulich) - correct comment. (suggested by Jan Beulich) - move 'cos_ref' array clearning into this patch. (suggested by Jan Beulich) - add 'alt_type' in 'feat_props' to handle some special operation in the future. (suggested by Jan Beulich) - move 'feat_init' out from the statement. (suggested by Jan Beulich) - change 'cat_init_feat' type to 'int' to return error back if something wrong. Then, we will not add feat_props into list. v12: - add comment for 'feat_init'. (suggested by Jan Beulich) - use 'ARRAY_SIZE()' to check array boundary. (suggested by Jan Beulich) - use 'XENLOG_WARNING' for error message. (suggested by Jan Beulich) - move 'type[]' assignment for feat_props object into its delcaration to make the object be 'const'. (suggested by Jan Beulich) - remove "L3" and "L2" indication in printk. (suggested by Jan Beulich) - move position of 'ref_lock' definition. - restore mask(0) MSR to default value. (suggested by Jan Beulich) v11: - handle 'feat_init'. - merge main data structures implementation into CPU init/free patch, including commit messages and change history. (suggested by Jan Beulich) - remove MSR restore action which is unnecessary. (suggested by Jan Beulich) - move 'type[]' declaration into this patch. (suggested by Jan Beulich) - modify comment. (suggested by Jan Beulich) v10: - remove initialization for 'PSR_SOCKET_L3_CAT'. (suggested by Jan Beulich) - rename 'feat_ops' to 'feat_props'. (suggested by Jan Beulich) - move 'cbm_len' to 'feat_props' because it is feature independent so far. (suggested by Jan Beulich) - move 'cos_max' to 'feat_props' because it is feature independent. (suggested by Jan Beulich) - move 'cos_num' to 'feat_props' because it is feature independent. (suggested by Jan Beulich) - remove union 'info' and struct 'psr_cat_hw_info'. - remove 'get_cos_max' from 'feat_props'. (suggested by Jan Beulich) - remove 'feat_mask' from 'psr_socket_info' because we can use 'features[]' to check if any feature is initialized. (suggested by Jan Beulich) - move 'ref_lock' above 'cos_ref'. (suggested by Jan Beulich) - adjust comments and commit message according to above changes. - remove 'asm/x86_emulate.h' inclusion as it has been indirectly included. (suggested by Jan Beulich) - remove 'CAT_COS_NUM' as it is only used once. (suggested by Jan Beulich) - remove 'feat_mask'. (suggested by Jan Beulich) - changes about 'feat_props'. (suggested by Jan Beulich) - remove 'get_cos_max' hook declaration. (suggested by Jan Beulich) - modify 'cat_default_val' implementation. (suggested by Jan Beulich) - modify 'psr_alloc_feat_enabled' implementation to make it simple. (suggested by Jan Beulich) - rename 'free_feature' to 'free_socket_resources' because it is executed when socket is offline. It needs free resources related to the socket. (suggested by Jan Beulich) - define 'feat_init_done' to iterate feature array to check if any feature has been initialized. (suggested by Jan Beulich) - input 'struct cpuid_leaf' pointer into 'cat_init_feature' to avoid memory copy. (suggested by Jan Beulich) - modify 'cat_init_feature' to use switch and things related to above changes. (suggested by Jan Beulich) - add an indentation for label. (suggested by Jan Beulich) v9: - replace feature list to a feature pointer array. (suggested by Roger Pau) - add 'PSR_SOCKET_MAX_FEAT' in 'enum psr_feat_type' to know features account. (suggested by Roger Pau) - move 'feat_ops' declaration into 'feat_node' structure. (suggested by Roger Pau) - directly use uninon for feature HW info and move its declaration into 'feat_node' structure. (suggested by Roger Pau) - remove 'enum psr_feat_type feature' declared in 'feat_ops' because it is not useful after using feature pointer array. (suggested by Roger Pau) - rename 'l3_cat_info' to 'cat_info' to be used by all CAT/CDP features. - remove 'nr_feat' which is only for a record. (suggested by Jan Beulich) - add 'cos_num' to record how many COS registers are used by a feature in one time access. (suggested by Jan Beulich) - replace 'uint64_t' to 'uint32_t' for cbm value because SDM specifies the max 32 bits for it. (suggested by Jan Beulich) - add commit message to explain the flows. - handle cpu offline and online again case to read MSRs registers values back and save them into cos array to make user can get real data. - create a new patch about moving 'cpuid_count_leaf'. (suggested by Wei Liu) - modify comment to explain why not free some resource in 'free_feature'. (suggested by Wei Liu) - implement 'psr_alloc_feat_enabled' to check if allocation feature is enabled in cmdline and some initialization work done. (suggested by Wei Liu) - implement 'cat_default_val' to set default value for CAT features. (suggested by Wei Liu) - replace feature list handling to feature array handling. (suggested by Roger Pau) - implement a common 'cat_init_feature' to replace L3 CAT/L2 CAT specific init functions. (suggested by Roger Pau) - modify comments for global feature node. (suggested by Jan Beulich) - remove unnecessary comments. (suggested by Jan Beulich) - remove unnecessary 'else'. (suggested by Jan Beulich) - remove 'nr_feat'. (suggested by Jan Beulich) - modify patch title to indicate 'L3 CAT'. (suggested by Jan Beulich) - check global flag with boot cpu operations. (suggested by Jan Beulich) - remove 'cpu_init_work' and move codes into 'psr_cpu_init'. (suggested by Jan Beulich) - remove 'cpu_fini_work' and move codes into 'psr_cpu_fini'. (suggested by Jan Beulich) - assign value for 'cos_num'. (suggested by Jan Beulich) - change about 'uint64_t' to 'uint32_t'. (suggested by Jan Beulich) v8: - fix format issue. (suggested by Konrad Rzeszutek Wilk) - add comments to explain why we care about cpumask_empty when the last cpu on socket is offline. (suggested by Konrad Rzeszutek Wilk) v7: - sort inclusion files position. (suggested by Wei Liu) - initialize structure objects for avoiding surprise. (suggested by Konrad Rzeszutek Wilk) - fix typo. (suggested by Konrad Rzeszutek Wilk) - fix a logical mistake when handling the last cpu offline event. (suggested by Konrad Rzeszutek Wilk) v6: - make commit message be clearer. (suggested by Konrad Rzeszutek Wilk) - fix wordings. (suggested by Konrad Rzeszutek Wilk) - add comments to explain relationship between 'feat_mask' and 'enum psr_feat_type'. (suggested by Konrad Rzeszutek Wilk) - use 'struct cpuid_leaf' introduced in Andrew's patch. (suggested by Konrad Rzeszutek Wilk) - add comments about cpu_add_remove_lock. (suggested by Konrad Rzeszutek Wilk) - change 'clear_bit' to '__clear_bit'. (suggested by Konrad Rzeszutek Wilk) - add 'ASSERT' check when setting 'feat_mask'. (suggested by Konrad Rzeszutek Wilk) - adjust 'printk' position to avoid odd spacing. (suggested by Konrad Rzeszutek Wilk) - add comment to explain usage of 'feat_l3_cat'. (suggested by Konrad Rzeszutek Wilk) - fix wording. (suggested by Konrad Rzeszutek Wilk) - move 'cpuid_count_leaf' helper function to 'asm-x86/processor.h'. It cannot be moved to 'cpuid.h' which causes compilation error because of header file loop reference. (suggested by Andrew Cooper) v5: - remove section number. (suggested by Jan Beulich) - remove double blank. (suggested by Jan Beulich) - add comment to explain the reason to define 'feat_l3_cat'. (suggested by Jan Beulich) - use 'list_for_each_entry_safe'. (suggested by Jan Beulich) - remove codes to free 'feat_l3_cat' in 'free_feature' to avoid the need for an allocation the next time a CPU comes online. (suggested by Jan Beulich) - define 'struct cpuid_leaf_regs' to encapsulate eax~edx. (suggested by Jan Beulich) - print feature info on a socket only when 'opt_cpu_info' is true. (suggested by Jan Beulich) - declare global variable 'l3_cat_ops' to 'static const'. (suggested by Jan Beulich) - use 'current_cpu_data'. (suggested by Jan Beulich) - rename 'feat_tmp' to 'feat'. (suggested by Jan Beulich) - clear PQE feature bit when the maximum CPUID level is too low. (suggested by Jan Beulich) - directly call 'l3_cat_init_feature'. No need to make it a callback function. (suggested by Jan Beulich) - remove local variable 'info'. (suggested by Jan Beulich) - move 'INIT_LIST_HEAD' into 'cpu_init_work' to be together with spin_lock_init(). (suggested by Jan Beulich) - remove 'cpu_prepare_work' and move its content into 'psr_cpu_prepare'. (suggested by Jan Beulich) v4: - create this patch because of removing all old CAT/CDP codes to make implementation be more easily understood. (suggested by Jan Beulich) --- xen/arch/x86/psr.c | 294 +++++++++++++++++++++++++++++++++++++++++++++- xen/include/asm-x86/psr.h | 1 + 2 files changed, 289 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c index 96a8589..39d8581 100644 --- a/xen/arch/x86/psr.c +++ b/xen/arch/x86/psr.c @@ -13,16 +13,118 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. */ -#include #include #include +#include #include #include +/* + * Terminology: + * - CAT Cache Allocation Technology + * - CBM Capacity BitMasks + * - CDP Code and Data Prioritization + * - CMT Cache Monitoring Technology + * - COS/CLOS Class of Service. Also mean COS registers. + * - COS_MAX Max number of COS for the feature (minus 1) + * - MSRs Machine Specific Registers + * - PSR Intel Platform Shared Resource + */ + #define PSR_CMT (1<<0) #define PSR_CAT (1<<1) #define PSR_CDP (1<<2) +#define CAT_CBM_LEN_MASK 0x1f +#define CAT_COS_MAX_MASK 0xffff + +/* + * Per SDM chapter 'Cache Allocation Technology: Cache Mask Configuration', + * the MSRs ranging from 0C90H through 0D0FH (inclusive), enables support for + * up to 128 L3 CAT Classes of Service. The COS_ID=[0,127]. + * + * The MSRs ranging from 0D10H through 0D4FH (inclusive), enables support for + * up to 64 L2 CAT COS. The COS_ID=[0,63]. + * + * So, the maximum COS register count of one feature is 128. + */ +#define MAX_COS_REG_CNT 128 + +/* + * Every PSR feature uses some COS registers for each COS ID, e.g. CDP uses 2 + * COS registers (DATA and CODE) for one COS ID, but CAT uses 1 COS register. + * We use below macro as the max number of COS registers used by all features. + * So far, it is 2 which means CDP's COS registers number. + */ +#define MAX_COS_NUM 2 + +enum psr_feat_type { + FEAT_TYPE_L3_CAT, + FEAT_TYPE_NUM, +}; + +/* + * This structure represents one feature. + * cos_max - The max COS registers number got through CPUID. + * cbm_len - The length of CBM got through CPUID. + * cos_reg_val - Array to store the values of COS registers. One entry stores + * the value of one COS register. + * For L3 CAT and L2 CAT, one entry corresponds to one COS_ID. + * For CDP, two entries correspond to one COS_ID. E.g. + * COS_ID=0 corresponds to cos_reg_val[0] (Data) and + * cos_reg_val[1] (Code). + */ +struct feat_node { + /* cos_max and cbm_len are common values for all features so far. */ + unsigned int cos_max; + unsigned int cbm_len; + uint32_t cos_reg_val[MAX_COS_REG_CNT]; +}; + +/* + * This structure defines feature specific values, e.g. cos_num. + * + * Array 'feat_props' is defined to save every feature's properties. We use + * 'enum psr_feat_type' as index. + */ +static const struct feat_props { + /* + * cos_num - COS registers number that feature uses for one COS ID. + * It is defined in SDM. + */ + unsigned int cos_num; + + /* + * An array to save all 'enum cbm_type' values of the feature. It is + * used with cos_num together to get/write a feature's COS registers + * values one by one. + */ + enum cbm_type type[MAX_COS_NUM]; + + /* + * alt_type is 'alternative type'. When this 'alt_type' is input, the + * feature does some special operations. + */ + enum cbm_type alt_type; +} *feat_props[FEAT_TYPE_NUM]; + +/* + * PSR features are managed per socket. Below structure defines the members + * used to manage these features. + * feat_init - Indicate if features on a socket have been initialized. + * features - A feature node array used to manage all features enabled. + * ref_lock - A lock to protect cos_ref. + * cos_ref - A reference count array to record how many domains are using the + * COS ID. Every entry of cos_ref corresponds to one COS ID. + */ +struct psr_socket_info { + bool feat_init; + /* Feature array's index is 'enum psr_feat_type' which is same as 'props' */ + struct feat_node *features[FEAT_TYPE_NUM]; + spinlock_t ref_lock; + unsigned int cos_ref[MAX_COS_REG_CNT]; +}; + struct psr_assoc { uint64_t val; uint64_t cos_mask; @@ -30,11 +132,105 @@ struct psr_assoc { struct psr_cmt *__read_mostly psr_cmt; +static struct psr_socket_info *__read_mostly socket_info; + static unsigned int opt_psr; static unsigned int __initdata opt_rmid_max = 255; +static unsigned int __read_mostly opt_cos_max = MAX_COS_REG_CNT; static uint64_t rmid_mask; static DEFINE_PER_CPU(struct psr_assoc, psr_assoc); +/* + * Declare global feature node for every feature to facilitate the feature + * array creation. It is used to transiently store a spare node. + */ +static struct feat_node *feat_l3; + +/* Common functions */ +#define cat_default_val(len) (0xffffffff >> (32 - (len))) + +/* + * Use this function to check if any allocation feature has been enabled + * in cmdline. + */ +static bool psr_alloc_feat_enabled(void) +{ + return !!socket_info; +} + +static void free_socket_resources(unsigned int socket) +{ + unsigned int i; + struct psr_socket_info *info = socket_info + socket; + + if ( !info ) + return; + + /* + * Free resources of features. The global feature object, e.g. feat_l3, + * may not be freed here if it is not added into array. It is simply being + * kept until the next CPU online attempt. + */ + for ( i = 0; i < ARRAY_SIZE(info->features); i++ ) + { + xfree(info->features[i]); + info->features[i] = NULL; + } + + info->feat_init = false; + + memset(info->cos_ref, 0, MAX_COS_REG_CNT * sizeof(unsigned int)); +} + +/* CAT common functions implementation. */ +static int cat_init_feature(const struct cpuid_leaf *regs, + struct feat_node *feat, + struct psr_socket_info *info, + enum psr_feat_type type) +{ + /* No valid value so do not enable feature. */ + if ( !regs->a || !regs->d ) + return -ENOENT; + + feat->cbm_len = (regs->a & CAT_CBM_LEN_MASK) + 1; + feat->cos_max = min(opt_cos_max, regs->d & CAT_COS_MAX_MASK); + + switch ( type ) + { + case FEAT_TYPE_L3_CAT: + if ( feat->cos_max < 1 ) + return -ENOENT; + + /* We reserve cos=0 as default cbm (all bits within cbm_len are 1). */ + feat->cos_reg_val[0] = cat_default_val(feat->cbm_len); + + wrmsrl(MSR_IA32_PSR_L3_MASK(0), cat_default_val(feat->cbm_len)); + + break; + + default: + return -ENOENT; + } + + /* Add this feature into array. */ + info->features[type] = feat; + + if ( !opt_cpu_info ) + return 0; + + printk(XENLOG_INFO "CAT: enabled on socket %u, cos_max:%u, cbm_len:%u\n", + cpu_to_socket(smp_processor_id()), feat->cos_max, feat->cbm_len); + + return 0; +} + +/* L3 CAT props */ +static const struct feat_props l3_cat_props = { + .cos_num = 1, + .type[0] = PSR_CBM_TYPE_L3, + .alt_type = PSR_CBM_TYPE_UNKNOWN, +}; + static void __init parse_psr_bool(char *s, char *value, char *feature, unsigned int mask) { @@ -74,6 +270,9 @@ static void __init parse_psr_param(char *s) if ( val_str && !strcmp(s, "rmid_max") ) opt_rmid_max = simple_strtoul(val_str, NULL, 0); + if ( val_str && !strcmp(s, "cos_max") ) + opt_cos_max = simple_strtoul(val_str, NULL, 0); + s = ss + 1; } while ( ss ); } @@ -229,19 +428,98 @@ void psr_domain_free(struct domain *d) psr_free_rmid(d); } -static int psr_cpu_prepare(unsigned int cpu) +static void __init init_psr(void) { + if ( opt_cos_max < 1 ) + { + printk(XENLOG_INFO "CAT: disabled, cos_max is too small\n"); + return; + } + + socket_info = xzalloc_array(struct psr_socket_info, nr_sockets); + + if ( !socket_info ) + { + printk(XENLOG_WARNING "Failed to alloc socket_info!\n"); + return; + } +} + +static void __init psr_free(void) +{ + xfree(socket_info); + socket_info = NULL; +} + +static int psr_cpu_prepare(void) +{ + if ( !psr_alloc_feat_enabled() ) + return 0; + + /* Malloc memory for the global feature node here. */ + if ( feat_l3 == NULL && + (feat_l3 = xzalloc(struct feat_node)) == NULL ) + return -ENOMEM; + return 0; } static void psr_cpu_init(void) { + struct psr_socket_info *info; + unsigned int socket, cpu = smp_processor_id(); + struct feat_node *feat; + struct cpuid_leaf regs; + + if ( !psr_alloc_feat_enabled() || !boot_cpu_has(X86_FEATURE_PQE) ) + goto assoc_init; + + if ( boot_cpu_data.cpuid_level < PSR_CPUID_LEVEL_CAT ) + { + setup_clear_cpu_cap(X86_FEATURE_PQE); + goto assoc_init; + } + + socket = cpu_to_socket(cpu); + info = socket_info + socket; + if ( info->feat_init ) + goto assoc_init; + + spin_lock_init(&info->ref_lock); + + cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 0, ®s); + if ( regs.b & PSR_RESOURCE_TYPE_L3 ) + { + cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 1, ®s); + + feat = feat_l3; + feat_l3 = NULL; + + if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CAT) ) + feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props; + else + feat_l3 = feat; + } + + info->feat_init = true; + + assoc_init: psr_assoc_init(); } static void psr_cpu_fini(unsigned int cpu) { - return; + unsigned int socket = cpu_to_socket(cpu); + + if ( !psr_alloc_feat_enabled() ) + return; + + /* + * We only free when we are the last CPU in the socket. The socket_cpumask + * is cleared prior to this notification code by remove_siblinginfo(). + */ + if ( socket_cpumask[socket] && cpumask_empty(socket_cpumask[socket]) ) + free_socket_resources(socket); } static int cpu_callback( @@ -253,7 +531,7 @@ static int cpu_callback( switch ( action ) { case CPU_UP_PREPARE: - rc = psr_cpu_prepare(cpu); + rc = psr_cpu_prepare(); break; case CPU_STARTING: psr_cpu_init(); @@ -282,10 +560,14 @@ static int __init psr_presmp_init(void) if ( (opt_psr & PSR_CMT) && opt_rmid_max ) init_psr_cmt(opt_rmid_max); - psr_cpu_prepare(0); + if ( opt_psr & PSR_CAT ) + init_psr(); + + if ( psr_cpu_prepare() ) + psr_free(); psr_cpu_init(); - if ( psr_cmt_enabled() ) + if ( psr_cmt_enabled() || psr_alloc_feat_enabled() ) register_cpu_notifier(&cpu_nfb); return 0; diff --git a/xen/include/asm-x86/psr.h b/xen/include/asm-x86/psr.h index 57f47e9..8141336 100644 --- a/xen/include/asm-x86/psr.h +++ b/xen/include/asm-x86/psr.h @@ -50,6 +50,7 @@ enum cbm_type { PSR_CBM_TYPE_L3, PSR_CBM_TYPE_L3_CODE, PSR_CBM_TYPE_L3_DATA, + PSR_CBM_TYPE_UNKNOWN, }; extern struct psr_cmt *psr_cmt;