From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 752AD3630A7 for ; Wed, 19 Aug 2026 23:01:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=192.198.163.17 ARC-Seal:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787180503; cv=fail; b=eIOVLUKRJ/kqI3cwSfwg299TvMdCvDddEQOa3E3H6muLkHHLYUFQFBSOu1zHQXVscGw6qBBkqyaC/WgAowXOq/IylhnKhErYmh9Ky4UKh/8CD5DbNJ7HsSYVhakqoYy4hO142iEDa4rp2KuSvmEmfy41ZhYQ5x6BS6GT7j764pw= ARC-Message-Signature:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787180503; c=relaxed/simple; bh=pHglwdHVPDC4dLNh7oGvX2t5+YlrN4RYzF0yqvQzR1k=; h=Message-ID:Date:Subject:To:CC:References:From:In-Reply-To: Content-Type:MIME-Version; b=G2vv79BnNKHq4bJytXj90/zB0b64+azXQJwx72Dzfy5GjO0KkuiXJX4QjNEBNWzpwKarVm4kParu/jA4TPfLjfIgnmbeOAoHnhHH/LZuyOHscTUnDHZGLESjd8cHEox1Oax6mBgYNZYLMIUCB3ydxmmlz44YZNzEOysjV4lvTh4= ARC-Authentication-Results:i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=WCrIdts0; arc=fail smtp.client-ip=192.198.163.17 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="WCrIdts0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1787180500; x=1818716500; h=message-id:date:subject:to:cc:references:from: in-reply-to:content-transfer-encoding:mime-version; bh=pHglwdHVPDC4dLNh7oGvX2t5+YlrN4RYzF0yqvQzR1k=; b=WCrIdts0Yilc5xCFACtZmI9HJfZyunx7Mt17FpFdjUhYAFhoPK7EGuXx V9O0JIWN8ACvMXgJlqBIzVyVfrsKFaWi8POHtKcny8zEMUhMkrg58F+ct oUJfj/cUnKe1XjLqyZjEx/5gk06ctps2SH1zdl6O6BzJxiSLrldlrugN0 jQJBpxhU64mwqS5CmKpPAt2ZKHG+mJJf2lhPbzxMCY/YcB9dcmWKeHmfm wGMV02TsmS3LP/Z88rfPEshynabl/67odUMNHcYl7KoZ7HyCu5Vd3w3xY sPv7GQs7j7JeKBwXw0kHmtYFFskZUqQQY7z9lIPtHs8mTeuTlVK1BufC0 w==; X-CSE-ConnectionGUID: +/x0t5RsTI2Q/t6bUgJj0w== X-CSE-MsgGUID: kXolCu69SjOjsi1OOaaQbw== X-IronPort-AV: E=McAfee;i="6800,10657,11880"; a="87579343" X-IronPort-AV: E=Sophos;i="6.25,232,1779174000"; d="scan'208";a="87579343" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa111.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2026 16:01:39 -0700 X-CSE-ConnectionGUID: kDLwhNT8Ql+AHB9cpVrX7A== X-CSE-MsgGUID: X8oZPFJJRFK0eM7igNoURw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,232,1779174000"; d="scan'208";a="270926588" Received: from fmsmsx903.amr.corp.intel.com ([10.18.126.92]) by fmviesa005.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Aug 2026 16:01:39 -0700 Received: from FMSMSX902.amr.corp.intel.com (10.18.126.91) by fmsmsx903.amr.corp.intel.com (10.18.126.92) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Wed, 19 Aug 2026 16:01:39 -0700 Received: from fmsedg902.ED.cps.intel.com (10.1.192.144) by FMSMSX902.amr.corp.intel.com (10.18.126.91) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45 via Frontend Transport; Wed, 19 Aug 2026 16:01:39 -0700 Received: from CY3PR05CU001.outbound.protection.outlook.com (40.93.201.2) by edgegateway.intel.com (192.55.55.82) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Wed, 19 Aug 2026 16:01:38 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=TCS8wrSwIc4IBZUISAClBDAdhfqNVA6F0aqEJuzZ+3twEQAV4sbX/m58ty40MS2rzoAFlHGMGRp+ZsDWFO0RVrAI1FksmCGXAm9pBJwDAUc625wUI4LoDyfN5awt6zN1yeoFYumgpVN7+NS57bdS7mD9h21QSE7ASwkmn2QaB8gIwnFMk+1knteySju3vaVeMEsFUfoV7vNphvDUe283KI7aDDQzYsmAF8w3xcMbyhMabqokckLQLQEdF5c3czml0L5ecwzyWmaiPPncmEhRHerDQix9xQQ4Tjue86/FlrntXrOg/Ekeu3Tfb0h00yPM4FHMLPONZ36lCo+kWfe2UA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=m2ScX9CYDAex7tGcXrgt18vWU0xv055fF6+pC9ibiFY=; b=rgv7poS5tWwojmv73TFoBA9j4sGlj5SwbFgcxky/uIvcBWt7TFuBhJmcZUzoewT93mhPDtsBlY3frJnIEyoaWloeOtrQprCamkHsl268i5tUokhyHf+KcB6UmwwG0591lRHObUxZBFjmuArSpFKLyvvV7hyCneS+fSCXm+VvoTZ653xtRbNHcrM6YLlR+Wu2T/KTlXn1Qc10vFm0qcxzR5CxSGmwybYRpBaV6d0wWzVt6hu9v6PGUwCSwjb+7VHrlQ9GLlI2TZGs6Og7J0OTxzhEFo+Cjca4I3q2NcEJwUQerM2GAktYz3RyJBhtSaIVjEcDqL+I0YPYXDqEf6+lUw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=intel.com; Received: from SJ2PR11MB8370.namprd11.prod.outlook.com (2603:10b6:a03:540::20) by MW4PR11MB6785.namprd11.prod.outlook.com (2603:10b6:303:20c::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 23:01:35 +0000 Received: from SJ2PR11MB8370.namprd11.prod.outlook.com ([fe80::b6cf:ce77:3cdf:7cc]) by SJ2PR11MB8370.namprd11.prod.outlook.com ([fe80::b6cf:ce77:3cdf:7cc%5]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 23:01:35 +0000 Message-ID: <9a86b245-916a-43ed-9bee-897aa3432a89@intel.com> Date: Wed, 19 Aug 2026 16:01:33 -0700 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v6 3/9] x86/resctrl: Parse ACPI ERDT table and save CACD cpumask for RMDD domains To: Chen Yu , CC: , , , , , , , , , References: <7eaafec96fb5494d3f4b927fa295d5b756f82c64.1784968626.git.yu.c.chen@intel.com> Content-Language: en-US From: Reinette Chatre In-Reply-To: <7eaafec96fb5494d3f4b927fa295d5b756f82c64.1784968626.git.yu.c.chen@intel.com> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-ClientProxiedBy: MW4PR03CA0292.namprd03.prod.outlook.com (2603:10b6:303:b5::27) To SJ2PR11MB8370.namprd11.prod.outlook.com (2603:10b6:a03:540::20) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ2PR11MB8370:EE_|MW4PR11MB6785:EE_ X-MS-Office365-Filtering-Correlation-Id: e65d1357-dce7-42ff-4f01-08defe45d186 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|23010399003|376014|7416014|1800799024|366016|6133799003|10067099003|11063799006|4143699003|5023799004|22082099003|18002099003|3023799007|56012099006; X-Microsoft-Antispam-Message-Info: 5XUuYZYU42Td+/6YrVEiuleD4tvHwGMehEDoWcss2daHQm5lzXWosu1KzxPZ2S56q00bZkPZp5SSkgKTOw8tD/bmOzSE0HPkYsNVhTJ83QLcIAJdxxGBQeE+J0CFMSM1AR6fzu1D9ibTi5ZYbsXtOrvLJmgQg3oay7b12grc/Cg01uPuyuNBoFf7Kf9hphMqZRpWQ7SqVFcDEL5G1RQb1EhhPt4VK4/K1i2Rn6BReYfzWytLZFl0m/e7kmBkPO8vFpWU8JtP7oyEMPTet9/G9EKAWKJp2IrdN+9wqxd/wBG1HXVJ4OPJ3CHGuTVz+ZeoaidABSZfyGIx2W//pArz9Rfvpyo59Bsb7/s23MsNKrMriUg0FNm55qUN+2mgqqZqY9BnvAJgu32wGbrdkxWvSDSldY4ftooCDOLMyD6X5mc1O8pXhnaSRAWgGYRyVqWF+lxDwYQJk0jrTSZoAlsnPEfVqHpYHk5KzH0ygNkoxRSAP3/aGkME9hvOhTZfP5uKob5g4aho6XVet7k62vZBGBxdnaK062cIwwCTmsFZwj7GeiTQdEqaTKUhwUrYoJwnjOcnyL5bf3SQu2Ee1yp5KtiLcfso/ZYK5b4UthtASZ+NtPc8XoE+xY7l5QdHGKM9zC0xPV0tnCWfI0I5hN4GNXbN1rDCfpyCrK33ifNg9mY= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SJ2PR11MB8370.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(23010399003)(376014)(7416014)(1800799024)(366016)(6133799003)(10067099003)(11063799006)(4143699003)(5023799004)(22082099003)(18002099003)(3023799007)(56012099006);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?RUZJbitsVHZYeEdQYlJITlZuSUpGaWpPd1lIdGxVRHN1THlOejVQclpUT1JG?= =?utf-8?B?RzJrQ0xLTVg0a3RrK0F5aW5PWmNMVWpjNW9hWWlnaThPREVLWnBmeTZTSXNq?= =?utf-8?B?V3dnaFVwaGJBa2wxb0o4WlpBbWRFRVE2OHMrZnZpQXhLeWpkd2pUMVZtU3Jv?= =?utf-8?B?VFQ1ODN0eGt5RUludUlCSWdtZE00bHVFa09SeWM3SVVJVVFPVnJIVVZPcXg1?= =?utf-8?B?WTRSWHBkdmdlbHhEcWYwUmVzTmZqYWY3TmlPbktJY3RJc0liOCtjV2ptTmZT?= =?utf-8?B?aDRqSW15aXNXV1FYZU5CNkFpbCtKY0swQTgyVDJxZlVOa1NmTjRyQXl2OHcy?= =?utf-8?B?aENIaUNaMkhLNmd6aWpMc2lUWVluT2ExSWxkMmozeDZOdllhTWdnWVVpd3B0?= =?utf-8?B?MXVoc05kK20reDMzMnBSYU9tQ2UwTnVUQXFhUXlCbDFmVkdKYWhQaFVBQnNM?= =?utf-8?B?MURPRVV4ZDVsS3FJemIvUS9TUGJEV3pCN09yaGxMa2dXdUxSdFoxMzk0UjIx?= =?utf-8?B?c3p0MllqVWZkV2haZ2hidUlEOEpSUVlOOENZd1JKUVkrT2lkL2xBa09yekpa?= =?utf-8?B?bWNZcXRBUDhieVIzMHJyNkNPTk95NmFWOGRjaVp6MlBGR0FsYjR5bGZocFVU?= =?utf-8?B?SC80N2djbHhGamREelFqNkxuQU15UDUzMisyeTZ3dk1LSG43SlN1UVdvekhT?= =?utf-8?B?NEtSeTNLdlQ4OWhxcWtEVkpreXRZVkd2bUt5M3pmVWdyS0ZUejhMcWNOUG91?= =?utf-8?B?TUxneElTUGE1M3EwV1FMN2tYNUt4NmJOU3ZldXpNdFNzMGYzbE9zUnZhZkcw?= =?utf-8?B?NWtpU0Rad1lRaVc4d2RPeEtaK0JMVUVuT2VwZnliRFk1MVZFK25YYlorRWho?= =?utf-8?B?d2dEeTE1SFloYWZwZXpwQnc5bVV6bkQ0SDBXNjB1dlJtTGppK21UQkNRRDNz?= =?utf-8?B?K3IvMXozUURnM3lBTGJuWDJqV3kxZjZ6bEtFME5LWmpGVkJOVWo5TXRITWQ3?= =?utf-8?B?OUhnU0VPU05INk11eXdLdFF6NWFZUG40ZE1uMzI3a0tJWnNmRzI5amszcHIv?= =?utf-8?B?RmVMVm82Mzk3aHNSK1VnLzQ0azhvenJ6clFldncvdkM2Sm1aZjVGZ1RRbXVP?= =?utf-8?B?S0djRWRWTHRQZlNvdlUrUlJvdk8zbFhNRnZqd3IwRTkvUVNSYjhtcG5KS2l6?= =?utf-8?B?M1JSZ0NoVXUraFQyUG15cVRKWU9NV0FmdmlSaTArYk9DUzkzeEthU0NtakNR?= =?utf-8?B?VVA5TTd0VVhBNkRNOGtmdlNNNVovVXdicDlMRHpvUWZKVU16ZVZSYnFPbnJa?= =?utf-8?B?STIvL1pMSFplMU5DRDFpNGpzOEhDSXdId0VoZ1IzZUtNU1Jza1lWK2Z6ZlBm?= =?utf-8?B?cWREOXZUZ3hQYmR4Y2tILzE0d2YxQUNYS0VlRTJyU3JzOHFtR0pMV3pPODlv?= =?utf-8?B?V3V4ZkpYaGNuZXBvRWdTdlhHcGlFSGtGYUcrN3lBVTNNUGpJd1lSL0ZxZ1F2?= =?utf-8?B?UHJNYmpmVk1pTkV1cmZIMDdoNmtvUmhNN0JhNVdFNzcwektxNmNOSmlESGRF?= =?utf-8?B?SnB4aGtleHAxN0xieC80ZGt6b3RLSmVBTUFoL2pnQzRMR2V6VTYvY3NYWFoz?= =?utf-8?B?SWU5dW53ZGRoV1JZN2lST2IwZXllS3NreC90T1JwR3FoWlVaZWI3SmNhRjBz?= =?utf-8?B?OWUwa0sycVl0cEJHdWNtbjVTYUkyaVNrQTlBL1ZCVDNySzBsajE4Y2JlTVVy?= =?utf-8?B?TjQ1SFZmVEJBUW92Q3JmNFhLYjJ5TVpiamRNcGk5VzNEaEpQUmY3ak4vNTMr?= =?utf-8?B?OVRCOXU3d1FocWlGc1NIZnh0eVI2eU5GRFMzeHYrNXh2RXBuc0ZmMkpuc0l0?= =?utf-8?B?Q3V3eE5rOFRxWjJZbDBXcDhWV1ZZMVpBV080WEozbWUvbWFiRXR4UzhqdG5n?= =?utf-8?B?NytaRytEMWNiamlzY09IdGV4RUp1M1RkOW5Pem9lWlFvb2NKVjVoNmNKNmRN?= =?utf-8?B?ckQxVTBvMlNNQkNucXB3QjlWZjBxSngyK0ZJMVlldzhkM3RyVHU0S3RUS0lx?= =?utf-8?B?dDJwRU9GZGxTTVVoRmttck9lUzJ6TGIvWWs5Q3RoS28wZzhSNnNpanh5M0ZK?= =?utf-8?B?dFFDQ2NZREhXRnlXb1NXc3orRnBGaktWY2ZEc3B1VWU4ZFhvRUhxaDV5eUhm?= =?utf-8?B?NkhDdCtncmhpdVBwVHZrU21oNnBOTkVuTDErNm1DUnlUeGNVTHVYcmtvS0Ur?= =?utf-8?B?dVhrQ3RHTnJhcjlscGxqYUgvaEI0ajlJNUVRSTkrYUlIRU5SYVg1QTJveGVB?= =?utf-8?B?NHhFc0RnVStnU1JsR1FKY0lUcWh2NVpKbS9NYkthdDMzbHZrLzh2SkZsWmJy?= =?utf-8?Q?deYOngQvYwSbdDH0=3D?= X-Exchange-RoutingPolicyChecked: njL77+34LuZmX5BxGI4bWCDn2dQKXrmp0pIMfxPazVK1UUJoJ0/UuG7lv2KrTnAl7T4E2EZ9j2OdUbDvLwKSI4GBF9QN300hKRyRWKxVCNQQuQwz8NQcDGinciTH7ZNVC0+hq1KKaquHoqKldwgoW+WPmuP5q5nlpVPpDqftjRRNHmzogC2K8x37dVYqPhZuXH6I0YEXAqRrd/QM37KfDikXA0mU3Is/3peFrtREDmZbXDIJMOUxS01GehHDQtfbjYLDwGOFY2kwHuBqjYNXtU6W4x6JavIZLJf0bKROjPUnvKutwGXiMA3+Q/JKqgAjbHQctu/Ujd4fvHrYfU9LkQ== X-MS-Exchange-CrossTenant-Network-Message-Id: e65d1357-dce7-42ff-4f01-08defe45d186 X-MS-Exchange-CrossTenant-AuthSource: SJ2PR11MB8370.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 23:01:35.5974 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: HL+jSHZ6QaThiw+OH6NLT9z5leLxTaNKbsK5FTwruc0L14U9ogSY9aLnR/y569hIjcaLhPMIJZ026B6O7J+Fd7i7PF9XjCpErfiORcmW0Zs= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW4PR11MB6785 X-OriginatorOrg: intel.com Hi Chenyu, On 7/25/26 2:22 AM, Chen Yu wrote: > From: Anil S Keshavamurthy > > Parse the RMDD subtables within the ERDT ACPI table and their nested > CACD entries to construct per-domain CPU masks. The changelog always needs to start with context. Please see "Changelog" in Documentation/process/maintainer-tip.rst for complete expectations. > > There is one ERDT table per platform. Each RMDD describes one resource I do not think what "RMDD" stands for has been introduced at this point yet. > management domain (RMD), also known as an L3 domain, and carries MMIO > base information for later monitoring support. > > For each RMDD, parse the associated CACD, map its x2APIC IDs to logical What is "CACD"? Please always expand acronym before its first use. > CPUs, and save the resulting CPU mask. This mask associates each ERDT > domain with the CPUs that belong to it and is used later when attaching > ERDT data to resctrl monitoring domains. Please let each patch description stand on its own without referring to later patches in series. If a patch provides capability in preparation for future changes then you can use language like, "Associate every ERDT domain with the CPUs that belong to it to prepare for attaching ERDT data to resctrl monitoring domains." > --- > arch/x86/kernel/cpu/resctrl/Makefile | 1 + > arch/x86/kernel/cpu/resctrl/core.c | 14 +- > arch/x86/kernel/cpu/resctrl/erdt.c | 266 +++++++++++++++++++++++++ > arch/x86/kernel/cpu/resctrl/internal.h | 31 +++ > 4 files changed, 311 insertions(+), 1 deletion(-) > create mode 100644 arch/x86/kernel/cpu/resctrl/erdt.c > > diff --git a/arch/x86/kernel/cpu/resctrl/Makefile b/arch/x86/kernel/cpu/resctrl/Makefile > index 273ddfa30836..2216ee084832 100644 > --- a/arch/x86/kernel/cpu/resctrl/Makefile > +++ b/arch/x86/kernel/cpu/resctrl/Makefile > @@ -2,6 +2,7 @@ > obj-$(CONFIG_X86_CPU_RESCTRL) += core.o rdtgroup.o monitor.o > obj-$(CONFIG_X86_CPU_RESCTRL) += ctrlmondata.o > obj-$(CONFIG_X86_CPU_RESCTRL_INTEL_AET) += intel_aet.o > +obj-$(CONFIG_X86_CPU_RESCTRL) += erdt.o > obj-$(CONFIG_RESCTRL_FS_PSEUDO_LOCK) += pseudo_lock.o > > # To allow define_trace.h's recursive include: > diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c > index 9c01d2562b7a..23925bcd71d7 100644 > --- a/arch/x86/kernel/cpu/resctrl/core.c > +++ b/arch/x86/kernel/cpu/resctrl/core.c > @@ -1013,6 +1013,7 @@ static __init void check_quirks(void) > > static __init bool get_rdt_resources(void) > { > + erdt_init(); > rdt_alloc_capable = get_rdt_alloc_resources(); > rdt_mon_capable = get_rdt_mon_resources(); > Functions are not expected to leave dangling state when they return failure. get_rdt_resources() returning false is considered a failure and now the caller is left to clean up the dangling state which is not a familiar pattern to use and thus something that can/will trip people. On top of this this implementation pushes the cleanup very far from even the caller making this unfamiliar pattern even harder to recognize. Please let get_rdt_resources() clean up after itself on failure to find any resources. > @@ -1114,7 +1115,7 @@ void resctrl_cpu_detect(struct cpuinfo_x86 *c) > } > } > > -static int __init resctrl_arch_late_init(void) > +static int __init __resctrl_arch_late_init(void) > { > struct rdt_resource *r; > int state, ret, i; > @@ -1157,6 +1158,15 @@ static int __init resctrl_arch_late_init(void) > return 0; > } > > +static int __init resctrl_arch_late_init(void) > +{ > + int ret = __resctrl_arch_late_init(); > + > + if (ret) > + erdt_exit(); > + return ret; > +} Related to earlier comment on cleanup I find this cleanup to be asymmentrical and inconsistent with how resctrl usually does cleanup. Why not do cleanup in (original) resctrl_arch_late_init() to be consistent with other cleanup when failures are encountered during initialization, for example, cpuhp_remove_state()? I find that having the cleanup handled where error is encountered is easier to understand. > + > late_initcall(resctrl_arch_late_init); > > static void __exit resctrl_arch_exit(void) > @@ -1166,6 +1176,8 @@ static void __exit resctrl_arch_exit(void) > cpuhp_remove_state(rdt_online); > > resctrl_exit(); > + > + erdt_exit(); Here the cleanup is indeed done in the same place as cleanup of other init work (cpuhp_remove_state()). > } > > __exitcall(resctrl_arch_exit); > diff --git a/arch/x86/kernel/cpu/resctrl/erdt.c b/arch/x86/kernel/cpu/resctrl/erdt.c > new file mode 100644 > index 000000000000..8998cae47090 > --- /dev/null > +++ b/arch/x86/kernel/cpu/resctrl/erdt.c > @@ -0,0 +1,266 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Enhanced Resource Director Technology (ERDT) > + * > + * Copyright (C) 2026 Intel Corporation > + * > + */ > + > +#define pr_fmt(fmt) "resctrl: " fmt > + > +#include > +#include > +#include > +#include > + > +#include > + > +#include "internal.h" > + > +static LIST_HEAD(domain_info_list); > + > +/* True when the ERDT ACPI table describes at least one domain with at least one CPU. */ > +static bool erdt_enabled; > + > +#define ERDT_VALID_VERSION 1 > +#define RMDD_FLAG_CPU_L3_DOMAIN BIT(0) > + > +/* Bitmask of valid sub-tables found in the first RMDD, used to ensure all RMDDs match. */ > +static u32 valid_subtbl_mask; > + > +/* Domain ID of the first RMDD that established @valid_subtbl_mask, for diagnostics. */ > +static u16 first_rmdd_domain_id; > + > +static int erdt_max_rmid; Could this ever be negative? Could this instead be of same type as the value it is initialized with? Looks like this will improve type safety with the min_t() usage then using the accurate and consistent type of both parameters? I also think a comment describing erdt_max_rmid will be helpful, especially considering that it has "max" in its name but then its value is determined using the *minimum* of all domains' RMID? > + > +int erdt_get_max_rmid(void) > +{ > + return erdt_max_rmid; > +} > + > +static void __iomem *erdt_ioremap(phys_addr_t base, u32 num_pages, const char *desc) > +{ > + void __iomem *addr; > + size_t size; > + > + if (check_mul_overflow(num_pages, SZ_4K, &size)) > + return NULL; > + > + addr = ioremap(base, size); The types seem to target a function with prototype ioremap(phys_addr_t base, size_t size) but I find arch/x86/include/asm/io.h to declare: void __iomem *ioremap(resource_size_t offset, unsigned long size); Since it is this code that determines the type it could just use matching accurate type from the beginning? > + if (!addr) > + pr_warn(FW_BUG "ERDT: Failed to map %s at phys addr %pa (size: %u pages)\n", > + desc, &base, num_pages); Please align to open parenthesis. > + > + return addr; > +} > + > +static void erdt_iounmap_domain(struct erdt_domain_info *domain) > +{ > + for (int i = 0; i < ERDT_MMIO_NUM_TYPES; i++) { > + if (domain->base[i]) { > + iounmap(domain->base[i]); > + domain->base[i] = NULL; > + } > + } > +} > + > +static void cleanup_one_domain(struct erdt_domain_info *d) > +{ > + erdt_iounmap_domain(d); > + kfree(d); > +} > + > +/* > + * Save CACD information for this RMDD: > + * convert the X2APIC to CPU and save them in a mask. > + */ > +static __init int cacd_init(struct acpi_subtbl_hdr_16 *subtbl, > + struct erdt_domain_info *domain_info) > +{ > + struct acpi_erdt_cacd *cacd = (struct acpi_erdt_cacd *)subtbl; > + int num_ids, cpu; Can num_ids ever be negative? If not, please use unsigned type. > + > + if (cacd->header.length < struct_size(cacd, X2APICIDS, 1)) { > + pr_warn(FW_BUG "Invalid x2apicid CACD table\n"); > + return -EIO; > + } > + > + num_ids = (cacd->header.length - sizeof(*cacd)) / sizeof(cacd->X2APICIDS[0]); > + > + for (int i = 0; i < num_ids; i++) { > + cpu = topo_lookup_cpuid(cacd->X2APICIDS[i]); > + if (cpu < 0) { > + pr_warn(FW_BUG "Unknown x2apicid 0x%x\n", cacd->X2APICIDS[i]); > + return -EIO; > + } > + > + cpumask_set_cpu(cpu, &domain_info->cpu_mask); > + } > + > + return 0; > +} > + > +static inline struct acpi_subtbl_hdr_16 *rmdd_subtbl(struct acpi_erdt_rmdd *rmdd) > +{ > + return (void *)rmdd + sizeof(*rmdd); > +} > + > +static inline struct acpi_subtbl_hdr_16 *next_subtbl(struct acpi_subtbl_hdr_16 *subtbl) > +{ > + return (void *)subtbl + subtbl->length; > +} > + > +static inline bool subtbl_valid(void *end, struct acpi_subtbl_hdr_16 *subtbl) > +{ > + /* Ensure the header is within bounds before dereferencing it. */ > + if ((void *)subtbl + sizeof(*subtbl) > end) > + return false; > + > + /* A sub-table must be at least as large as its header. */ > + if (subtbl->length < sizeof(*subtbl)) > + return false; > + > + /* The entire sub-table (including body) must fit within the parent. */ > + if ((void *)subtbl + subtbl->length > end) > + return false; > + > + return true; > +} > + > +static __init bool parse_rmdd_table(struct acpi_subtbl_hdr_16 *rmdd_hdr) > +{ > + struct erdt_domain_info *domain_info; > + struct acpi_subtbl_hdr_16 *subtbl; > + struct acpi_erdt_rmdd *rmdd; > + u32 subtbl_mask = 0; > + > + if (rmdd_hdr->length < sizeof(*rmdd)) { > + pr_warn(FW_BUG "Invalid RMDD length %u bytes\n", rmdd_hdr->length); > + return false; > + } > + > + rmdd = (struct acpi_erdt_rmdd *)rmdd_hdr; Could this initialization be done at time of declaration to be consistent with the other functions parsing tables? The length comparison could then use rmdd->header.length to match how this check is done in all the other places. Being consistent makes the code much easier to understand. > + > + /* Quietly ignore non-CPU-based L3 domains */ > + if (!(rmdd->flags & RMDD_FLAG_CPU_L3_DOMAIN)) > + return true; > + > + domain_info = kzalloc_obj(*domain_info, GFP_KERNEL); > + if (!domain_info) > + return false; > + > + domain_info->dom_id = -1; > + > + domain_info->base[ERDT_MMIO_RMDD_CREG] = > + erdt_ioremap(rmdd->creg_base, rmdd->creg_size, "RMDD ctrl base"); > + if (!domain_info->base[ERDT_MMIO_RMDD_CREG]) > + goto cleanup; > + > + for (subtbl = rmdd_subtbl(rmdd); > + subtbl_valid((void *)rmdd + rmdd->header.length, subtbl); > + subtbl = next_subtbl(subtbl)) { I find it curious how the implementation varies in how the tables are parsed. For example, here it uses a for () loop to cycle through the tables while enumerate_erdt_table() uses a while() loop for what appears to be the same flow. Are they actually different? Why are the two different patterns needed? > + switch (subtbl->type) { > + /* An RMDD table has one or more CACD sub-table(s) */ > + case ACPI_ERDT_TYPE_CACD: > + if (cacd_init(subtbl, domain_info)) > + goto cleanup; > + > + subtbl_mask |= BIT(ACPI_ERDT_TYPE_CACD); > + break; > + default: > + break; > + } > + } > + > + if (!subtbl_mask) > + goto cleanup; > + > + /* > + * Require all RMDDs to support same set of sub-tables > + */ > + if (!valid_subtbl_mask) { > + valid_subtbl_mask = subtbl_mask; > + first_rmdd_domain_id = rmdd->domain_id; > + } else if (subtbl_mask != valid_subtbl_mask) { > + pr_warn(FW_BUG "RMDD %u sub-table set does not match the first RMDD %u\n", > + rmdd->domain_id, first_rmdd_domain_id); > + goto cleanup; > + } > + > + if (!rmdd->max_rmid) { > + pr_warn(FW_BUG "Unreasonable RMDD max_rmid %u\n", rmdd->max_rmid); > + goto cleanup; > + } > + domain_info->max_rmid = rmdd->max_rmid; > + > + if (!erdt_max_rmid) > + erdt_max_rmid = rmdd->max_rmid; > + else > + erdt_max_rmid = min_t(int, erdt_max_rmid, rmdd->max_rmid); > + > + list_add(&domain_info->entry, &domain_info_list); > + > + return true; > + > +cleanup: > + cleanup_one_domain(domain_info); > + return false; > +} > + > +void erdt_exit(void) > +{ > + struct erdt_domain_info *d, *tmp; > + > + list_for_each_entry_safe(d, tmp, &domain_info_list, entry) { > + list_del(&d->entry); > + cleanup_one_domain(d); > + } > + erdt_enabled = false; > + valid_subtbl_mask = 0; > + first_rmdd_domain_id = 0; Should erdt_max_rmid be reset also? > +} > + > +static __init int enumerate_erdt_table(struct acpi_table_header *table_hdr) > +{ > + struct acpi_table_erdt *erdt = (struct acpi_table_erdt *)table_hdr; > + struct acpi_subtbl_hdr_16 *subtbl; > + void *table_end; > + > + if (erdt->header.revision != ERDT_VALID_VERSION) { > + pr_info("Unsupported ERDT table revision %u (expected %u)\n", > + erdt->header.revision, ERDT_VALID_VERSION); > + return -EINVAL; > + } > + > + if (erdt->header.length < sizeof(*erdt)) { > + pr_warn(FW_BUG "ERDT: Invalid table length %u bytes\n", erdt->header.length); > + return -EINVAL; > + } > + > + subtbl = (void *)erdt + sizeof(struct acpi_table_erdt); Please use sizeof(*erdt) > + table_end = (void *)erdt + erdt->header.length; > + > + while (subtbl_valid(table_end, subtbl)) { > + if (subtbl->type == ACPI_ERDT_TYPE_RMDD && > + !parse_rmdd_table(subtbl)) > + goto cleanup; > + > + subtbl = next_subtbl(subtbl); > + } > + > + if (list_empty(&domain_info_list)) > + goto cleanup; > + > + erdt_enabled = true; > + > + return 0; > + > +cleanup: > + erdt_exit(); > + return -EINVAL; > +} > + > +int __init erdt_init(void) > +{ > + return acpi_table_parse(ACPI_SIG_ERDT, enumerate_erdt_table); > +} > diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h > index e3cfa0c10e92..bdff3ea36e62 100644 > --- a/arch/x86/kernel/cpu/resctrl/internal.h > +++ b/arch/x86/kernel/cpu/resctrl/internal.h > @@ -21,6 +21,33 @@ > > #define RMID_VAL_UNAVAIL BIT_ULL(62) > > +/* > + * Index into erdt_domain_info::base[] for each MMIO region. > + * @ERDT_MMIO_RMDD_CREG: RMDD control register base address > + */ > +enum erdt_mmio_type { > + ERDT_MMIO_RMDD_CREG, > + ERDT_MMIO_LAST = ERDT_MMIO_RMDD_CREG > +}; > + > +#define ERDT_MMIO_NUM_TYPES (ERDT_MMIO_LAST + 1) > + > +/** > + * struct erdt_domain_info - Per-domain ERDT information > + * @base: Array of ioremapped MMIO region base addresses, indexed by ERDT_MMIO_* type I think "type" can be dropped? The enum is already implicitly an "MMIO type"? > + * @cpu_mask: CPUs belonging to this resource management domain > + * @max_rmid: Maximum RMID supported by this domain > + * @dom_id: L3 cache ID shared by all CPUs in this domain (-1 if unset) > + * @entry: Links into the global domain_info_list > + */ > +struct erdt_domain_info { > + void __iomem *base[ERDT_MMIO_NUM_TYPES]; > + struct cpumask cpu_mask; > + u32 max_rmid; > + int dom_id; > + struct list_head entry; > +}; > + > /* > * With the above fields in use 62 bits remain in MSR_IA32_QM_CTR for > * data to be returned. The counter width is discovered from the hardware > @@ -253,4 +280,8 @@ static inline void intel_aet_mon_domain_setup(int cpu, int id, struct rdt_resour > static inline bool intel_handle_aet_option(bool force_off, char *tok) { return false; } > #endif > > +int erdt_get_max_rmid(void); > +int erdt_init(void); > +void erdt_exit(void); > + > #endif /* _ASM_X86_RESCTRL_INTERNAL_H */ Reinette