From patchwork Thu Dec 5 22:23:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 13896041 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.18]) (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 65D2F1CCEF8 for ; Thu, 5 Dec 2024 22:23:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437405; cv=none; b=TblFfAkI56m5HxACbp3bI8HPgdlNbqOUucGGsUeqke49Ar37RehUI7EHQGN5FRAcQJZkQnGb2/9dBT9xKCjpU/iQ6NkeVKdHDg5ae+Di/28xyCZP3yOMGXecSp/VnA2QJPnnqPApOwM3GNDcErnxWaX3maj01rlx2QlGURIMSqs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437405; c=relaxed/simple; bh=N/yHfUxNx+wHAKz81sl19z55StoOGiF93MdG+BsYVJE=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=u0phxQ9Qg0cNaICH1CD+rp2Cm2P+LBxFI5zlqOurJW5ewP7XQiIpjE9Quq/LpM1raMr0V1imQQUST5VvbsNe549tpuWjANrY1J1YMS5sAxmpbdOS4tUflH1dVM4kqYUrc59ruPXMMRPXXmIfqAhhbqYaS/RETeBa3BkEU81MTQM= ARC-Authentication-Results: i=1; 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=ZvHugNDM; arc=none smtp.client-ip=198.175.65.18 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="ZvHugNDM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733437403; x=1764973403; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=N/yHfUxNx+wHAKz81sl19z55StoOGiF93MdG+BsYVJE=; b=ZvHugNDMCveTPs1JWRMs0Ta5pMZZn1Mwa0F7Ittjyk2HyOu4j2VRDEzB LlBkeLu3oKuPT+Tqk/7ncGah5kg7QNW2bfsTootDC7C1ruVzuCl5WWD44 o60wH3cE0novP686tBuxtie9tIWdTs1ZRDYpgCcwLjTytmfZUAMOljgOD NP2g/Adc15Obj/ZTRB/vqSiLKbgr1UhF+GmhzVt/dYIdOPdQdu8NT3+me UAZwf7jzGW2OlkI3uTz13EQwHR4lcz78TjnQFzpasNf/rubnm152fp2vW 3M+HSdfuRI4cvt4LPRkGlpjd9y7dRfQjRChN0Q2+BEF5BG3F2lbmg4ZwE Q==; X-CSE-ConnectionGUID: 3Lzq5cKtTAeQR9Z0+WY9SA== X-CSE-MsgGUID: 8kV7gjfuQme4czCci8wBQA== X-IronPort-AV: E=McAfee;i="6700,10204,11277"; a="33921122" X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="33921122" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:23 -0800 X-CSE-ConnectionGUID: ucvxB8e9SMmOxQpPNb5HJw== X-CSE-MsgGUID: tDJCinpKRO2DW13/H11a8g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="93905513" Received: from kcaccard-desk.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.125.108.178]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:22 -0800 Subject: [PATCH 01/11] configfs-tsm: Namespace TSM report symbols From: Dan Williams To: linux-coco@lists.linux.dev Cc: Yilun Xu , Samuel Ortiz , Alexey Kardashevskiy , Tom Lendacky , Sami Mujawar , Steven Price , Suzuki K Poulose , linux-pci@vger.kernel.org, gregkh@linuxfoundation.org Date: Thu, 05 Dec 2024 14:23:21 -0800 Message-ID: <173343740180.1074769.15809313632664416174.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> References: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In preparation for new + common TSM (TEE Security Manager) infrastructure, namespace the TSM report symbols in tsm.h with an _REPORT suffix to differentiate them from other incoming tsm work. Cc: Yilun Xu Cc: Samuel Ortiz Cc: Alexey Kardashevskiy Cc: Tom Lendacky Cc: Sami Mujawar Cc: Steven Price Cc: Suzuki K Poulose Signed-off-by: Dan Williams Reviewed-by: Alexey Kardashevskiy Reviewed-by: Suzuki K Poulose --- Documentation/ABI/testing/configfs-tsm-report | 0 MAINTAINERS | 2 + drivers/virt/coco/arm-cca-guest/arm-cca-guest.c | 8 +++--- drivers/virt/coco/sev-guest/sev-guest.c | 12 ++++----- drivers/virt/coco/tdx-guest/tdx-guest.c | 8 +++--- drivers/virt/coco/tsm.c | 32 ++++++++++++----------- include/linux/tsm.h | 22 ++++++++-------- 7 files changed, 42 insertions(+), 42 deletions(-) rename Documentation/ABI/testing/{configfs-tsm => configfs-tsm-report} (100%) diff --git a/Documentation/ABI/testing/configfs-tsm b/Documentation/ABI/testing/configfs-tsm-report similarity index 100% rename from Documentation/ABI/testing/configfs-tsm rename to Documentation/ABI/testing/configfs-tsm-report diff --git a/MAINTAINERS b/MAINTAINERS index 1e930c7a58b1..53f04c499705 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23842,7 +23842,7 @@ TRUSTED SECURITY MODULE (TSM) ATTESTATION REPORTS M: Dan Williams L: linux-coco@lists.linux.dev S: Maintained -F: Documentation/ABI/testing/configfs-tsm +F: Documentation/ABI/testing/configfs-tsm-report F: drivers/virt/coco/tsm.c F: include/linux/tsm.h diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c index 488153879ec9..63b9fdb843fa 100644 --- a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c +++ b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c @@ -95,7 +95,7 @@ static int arm_cca_report_new(struct tsm_report *report, void *data) struct arm_cca_token_info info; void *buf; u8 *token __free(kvfree) = NULL; - struct tsm_desc *desc = &report->desc; + struct tsm_report_desc *desc = &report->desc; if (desc->inblob_len < 32 || desc->inblob_len > 64) return -EINVAL; @@ -180,7 +180,7 @@ static int arm_cca_report_new(struct tsm_report *report, void *data) return ret; } -static const struct tsm_ops arm_cca_tsm_ops = { +static const struct tsm_report_ops arm_cca_tsm_ops = { .name = KBUILD_MODNAME, .report_new = arm_cca_report_new, }; @@ -201,7 +201,7 @@ static int __init arm_cca_guest_init(void) if (!is_realm_world()) return -ENODEV; - ret = tsm_register(&arm_cca_tsm_ops, NULL); + ret = tsm_report_register(&arm_cca_tsm_ops, NULL); if (ret < 0) pr_err("Error %d registering with TSM\n", ret); @@ -215,7 +215,7 @@ module_init(arm_cca_guest_init); */ static void __exit arm_cca_guest_exit(void) { - tsm_unregister(&arm_cca_tsm_ops); + tsm_report_unregister(&arm_cca_tsm_ops); } module_exit(arm_cca_guest_exit); diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c index fca5c45ed5cd..7eedde61589c 100644 --- a/drivers/virt/coco/sev-guest/sev-guest.c +++ b/drivers/virt/coco/sev-guest/sev-guest.c @@ -701,7 +701,7 @@ struct snp_msg_cert_entry { static int sev_svsm_report_new(struct tsm_report *report, void *data) { unsigned int rep_len, man_len, certs_len; - struct tsm_desc *desc = &report->desc; + struct tsm_report_desc *desc = &report->desc; struct svsm_attest_call ac = {}; unsigned int retry_count; void *rep, *man, *certs; @@ -836,7 +836,7 @@ static int sev_svsm_report_new(struct tsm_report *report, void *data) static int sev_report_new(struct tsm_report *report, void *data) { struct snp_msg_cert_entry *cert_table; - struct tsm_desc *desc = &report->desc; + struct tsm_report_desc *desc = &report->desc; struct snp_guest_dev *snp_dev = data; struct snp_msg_report_resp_hdr hdr; const u32 report_size = SZ_4K; @@ -965,7 +965,7 @@ static bool sev_report_bin_attr_visible(int n) return false; } -static struct tsm_ops sev_tsm_ops = { +static struct tsm_report_ops sev_tsm_report_ops = { .name = KBUILD_MODNAME, .report_new = sev_report_new, .report_attr_visible = sev_report_attr_visible, @@ -974,7 +974,7 @@ static struct tsm_ops sev_tsm_ops = { static void unregister_sev_tsm(void *data) { - tsm_unregister(&sev_tsm_ops); + tsm_report_unregister(&sev_tsm_report_ops); } static int __init sev_guest_probe(struct platform_device *pdev) @@ -1062,9 +1062,9 @@ static int __init sev_guest_probe(struct platform_device *pdev) mdesc->input.data_gpa = __pa(mdesc->certs_data); /* Set the privlevel_floor attribute based on the vmpck_id */ - sev_tsm_ops.privlevel_floor = vmpck_id; + sev_tsm_report_ops.privlevel_floor = vmpck_id; - ret = tsm_register(&sev_tsm_ops, snp_dev); + ret = tsm_report_register(&sev_tsm_report_ops, snp_dev); if (ret) goto e_free_cert_data; diff --git a/drivers/virt/coco/tdx-guest/tdx-guest.c b/drivers/virt/coco/tdx-guest/tdx-guest.c index d7db6c824e13..66ea09207a7c 100644 --- a/drivers/virt/coco/tdx-guest/tdx-guest.c +++ b/drivers/virt/coco/tdx-guest/tdx-guest.c @@ -163,7 +163,7 @@ static int tdx_report_new(struct tsm_report *report, void *data) { u8 *buf, *reportdata = NULL, *tdreport = NULL; struct tdx_quote_buf *quote_buf = quote_data; - struct tsm_desc *desc = &report->desc; + struct tsm_report_desc *desc = &report->desc; int ret; u64 err; @@ -299,7 +299,7 @@ static const struct x86_cpu_id tdx_guest_ids[] = { }; MODULE_DEVICE_TABLE(x86cpu, tdx_guest_ids); -static const struct tsm_ops tdx_tsm_ops = { +static const struct tsm_report_ops tdx_tsm_ops = { .name = KBUILD_MODNAME, .report_new = tdx_report_new, .report_attr_visible = tdx_report_attr_visible, @@ -324,7 +324,7 @@ static int __init tdx_guest_init(void) goto free_misc; } - ret = tsm_register(&tdx_tsm_ops, NULL); + ret = tsm_report_register(&tdx_tsm_ops, NULL); if (ret) goto free_quote; @@ -341,7 +341,7 @@ module_init(tdx_guest_init); static void __exit tdx_guest_exit(void) { - tsm_unregister(&tdx_tsm_ops); + tsm_report_unregister(&tdx_tsm_ops); free_quote_buf(quote_data); misc_deregister(&tdx_misc_dev); } diff --git a/drivers/virt/coco/tsm.c b/drivers/virt/coco/tsm.c index 9432d4e303f1..bcb515b50c68 100644 --- a/drivers/virt/coco/tsm.c +++ b/drivers/virt/coco/tsm.c @@ -13,7 +13,7 @@ #include static struct tsm_provider { - const struct tsm_ops *ops; + const struct tsm_report_ops *ops; void *data; } provider; static DECLARE_RWSEM(tsm_rwsem); @@ -98,7 +98,7 @@ static ssize_t tsm_report_privlevel_store(struct config_item *cfg, * SEV-SNP GHCB) and a minimum of a TSM selected floor value no less * than 0. */ - if (provider.ops->privlevel_floor > val || val > TSM_PRIVLEVEL_MAX) + if (provider.ops->privlevel_floor > val || val > TSM_REPORT_PRIVLEVEL_MAX) return -EINVAL; guard(rwsem_write)(&tsm_rwsem); @@ -202,7 +202,7 @@ static ssize_t tsm_report_inblob_write(struct config_item *cfg, memcpy(report->desc.inblob, buf, count); return count; } -CONFIGFS_BIN_ATTR_WO(tsm_report_, inblob, NULL, TSM_INBLOB_MAX); +CONFIGFS_BIN_ATTR_WO(tsm_report_, inblob, NULL, TSM_REPORT_INBLOB_MAX); static ssize_t tsm_report_generation_show(struct config_item *cfg, char *buf) { @@ -272,7 +272,7 @@ static ssize_t tsm_report_read(struct tsm_report *report, void *buf, size_t count, enum tsm_data_select select) { struct tsm_report_state *state = to_state(report); - const struct tsm_ops *ops; + const struct tsm_report_ops *ops; ssize_t rc; /* try to read from the existing report if present and valid... */ @@ -314,7 +314,7 @@ static ssize_t tsm_report_outblob_read(struct config_item *cfg, void *buf, return tsm_report_read(report, buf, count, TSM_REPORT); } -CONFIGFS_BIN_ATTR_RO(tsm_report_, outblob, NULL, TSM_OUTBLOB_MAX); +CONFIGFS_BIN_ATTR_RO(tsm_report_, outblob, NULL, TSM_REPORT_OUTBLOB_MAX); static ssize_t tsm_report_auxblob_read(struct config_item *cfg, void *buf, size_t count) @@ -323,7 +323,7 @@ static ssize_t tsm_report_auxblob_read(struct config_item *cfg, void *buf, return tsm_report_read(report, buf, count, TSM_CERTS); } -CONFIGFS_BIN_ATTR_RO(tsm_report_, auxblob, NULL, TSM_OUTBLOB_MAX); +CONFIGFS_BIN_ATTR_RO(tsm_report_, auxblob, NULL, TSM_REPORT_OUTBLOB_MAX); static ssize_t tsm_report_manifestblob_read(struct config_item *cfg, void *buf, size_t count) @@ -332,7 +332,7 @@ static ssize_t tsm_report_manifestblob_read(struct config_item *cfg, void *buf, return tsm_report_read(report, buf, count, TSM_MANIFEST); } -CONFIGFS_BIN_ATTR_RO(tsm_report_, manifestblob, NULL, TSM_OUTBLOB_MAX); +CONFIGFS_BIN_ATTR_RO(tsm_report_, manifestblob, NULL, TSM_REPORT_OUTBLOB_MAX); static struct configfs_attribute *tsm_report_attrs[] = { [TSM_REPORT_GENERATION] = &tsm_report_attr_generation, @@ -448,9 +448,9 @@ static struct configfs_subsystem tsm_configfs = { .su_mutex = __MUTEX_INITIALIZER(tsm_configfs.su_mutex), }; -int tsm_register(const struct tsm_ops *ops, void *priv) +int tsm_report_register(const struct tsm_report_ops *ops, void *priv) { - const struct tsm_ops *conflict; + const struct tsm_report_ops *conflict; guard(rwsem_write)(&tsm_rwsem); conflict = provider.ops; @@ -463,9 +463,9 @@ int tsm_register(const struct tsm_ops *ops, void *priv) provider.data = priv; return 0; } -EXPORT_SYMBOL_GPL(tsm_register); +EXPORT_SYMBOL_GPL(tsm_report_register); -int tsm_unregister(const struct tsm_ops *ops) +int tsm_report_unregister(const struct tsm_report_ops *ops) { guard(rwsem_write)(&tsm_rwsem); if (ops != provider.ops) @@ -474,11 +474,11 @@ int tsm_unregister(const struct tsm_ops *ops) provider.data = NULL; return 0; } -EXPORT_SYMBOL_GPL(tsm_unregister); +EXPORT_SYMBOL_GPL(tsm_report_unregister); static struct config_group *tsm_report_group; -static int __init tsm_init(void) +static int __init tsm_report_init(void) { struct config_group *root = &tsm_configfs.su_group; struct config_group *tsm; @@ -499,14 +499,14 @@ static int __init tsm_init(void) return 0; } -module_init(tsm_init); +module_init(tsm_report_init); -static void __exit tsm_exit(void) +static void __exit tsm_report_exit(void) { configfs_unregister_default_group(tsm_report_group); configfs_unregister_subsystem(&tsm_configfs); } -module_exit(tsm_exit); +module_exit(tsm_report_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Provide Trusted Security Module attestation reports via configfs"); diff --git a/include/linux/tsm.h b/include/linux/tsm.h index 11b0c525be30..431054810dca 100644 --- a/include/linux/tsm.h +++ b/include/linux/tsm.h @@ -6,17 +6,17 @@ #include #include -#define TSM_INBLOB_MAX 64 -#define TSM_OUTBLOB_MAX SZ_32K +#define TSM_REPORT_INBLOB_MAX 64 +#define TSM_REPORT_OUTBLOB_MAX SZ_32K /* * Privilege level is a nested permission concept to allow confidential * guests to partition address space, 4-levels are supported. */ -#define TSM_PRIVLEVEL_MAX 3 +#define TSM_REPORT_PRIVLEVEL_MAX 3 /** - * struct tsm_desc - option descriptor for generating tsm report blobs + * struct tsm_report_desc - option descriptor for generating tsm report blobs * @privlevel: optional privilege level to associate with @outblob * @inblob_len: sizeof @inblob * @inblob: arbitrary input data @@ -24,10 +24,10 @@ * @service_guid: optional service-provider service guid to attest * @service_manifest_version: optional service-provider service manifest version requested */ -struct tsm_desc { +struct tsm_report_desc { unsigned int privlevel; size_t inblob_len; - u8 inblob[TSM_INBLOB_MAX]; + u8 inblob[TSM_REPORT_INBLOB_MAX]; char *service_provider; guid_t service_guid; unsigned int service_manifest_version; @@ -44,7 +44,7 @@ struct tsm_desc { * @manifestblob: (optional) manifest data associated with the report */ struct tsm_report { - struct tsm_desc desc; + struct tsm_report_desc desc; size_t outblob_len; u8 *outblob; size_t auxblob_len; @@ -88,7 +88,7 @@ enum tsm_bin_attr_index { }; /** - * struct tsm_ops - attributes and operations for tsm instances + * struct tsm_report_ops - attributes and operations for tsm_report instances * @name: tsm id reflected in /sys/kernel/config/tsm/report/$report/provider * @privlevel_floor: convey base privlevel for nested scenarios * @report_new: Populate @report with the report blob and auxblob @@ -99,7 +99,7 @@ enum tsm_bin_attr_index { * Implementation specific ops, only one is expected to be registered at * a time i.e. only one of "sev-guest", "tdx-guest", etc. */ -struct tsm_ops { +struct tsm_report_ops { const char *name; unsigned int privlevel_floor; int (*report_new)(struct tsm_report *report, void *data); @@ -107,6 +107,6 @@ struct tsm_ops { bool (*report_bin_attr_visible)(int n); }; -int tsm_register(const struct tsm_ops *ops, void *priv); -int tsm_unregister(const struct tsm_ops *ops); +int tsm_report_register(const struct tsm_report_ops *ops, void *priv); +int tsm_report_unregister(const struct tsm_report_ops *ops); #endif /* __TSM_H */ From patchwork Thu Dec 5 22:23:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 13896042 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.18]) (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 E0D0C1CCEF8 for ; Thu, 5 Dec 2024 22:23:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437411; cv=none; b=DQf7M5kmXlfJuEN8B7sJqViJniy804NdoMNkEKisYfKElLQLniPEcwsN7iL4+n2uYaupkxCPy9uVZZsnMpIf03hWwmBmPvEitQfcqDdvbY8tJIlIT8jq431VhIOb9eswgQahopStkkz5nfr36wxueHyR6KxrqcXOTMW6ABzZOX0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437411; c=relaxed/simple; bh=LiJbKNs0v4zJbWcVmgIaWJfTF8G2NAh9EzD9TZKTjOU=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=CRluOkIMW6w1MjTt/1zuWNukjenQMBpOmBKE/rI0XRl5SaiCvLDyDQg0jVEAXa9gmKAOEd0PhuO+snLIDI1dyJC9FJWu069LosFGsIdiOm0A+5X2I4phR/tzjzQyv6nFAA3P4VhcHTcVbOhkKxkqReSBF6OkuygDDPHtl//2dwU= ARC-Authentication-Results: i=1; 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=UjEvO+Lz; arc=none smtp.client-ip=198.175.65.18 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="UjEvO+Lz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733437409; x=1764973409; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=LiJbKNs0v4zJbWcVmgIaWJfTF8G2NAh9EzD9TZKTjOU=; b=UjEvO+LzHxYiKWX5IpVfPZl8r0gJM2Tv1Xo0dSNS20QdJr4ZTtpDArK/ mKym0+crM+0/0k3qZEtYiia2beOV66jVGs/OHz36NzjFCmN0NP36c6k1Q ZEDS8uInGSD6myUWRxwWZ8fXeVnBrzRcQRFLFoagyktPGbIIXvmQZ6zsg gUUZRB+TJ34FhT80e6bRQ0m0o/PRoE2j2U53IYLRdpJFHkyb10qnz85HV gjX0mog63OYwB/tCg7OvMN2VYnyDukcr5OuaV4WNrN2aW41w0ZMZyOqM6 HEn0Z+vPCBAJAnfGx25v6Mtt40ugzQqjxs1BwBJcohFSoJU7bTFuVwJEe g==; X-CSE-ConnectionGUID: uOGhj8YBQlGENKCNGQ/UNw== X-CSE-MsgGUID: 9rUP/RidSWijZZcHbMtZQw== X-IronPort-AV: E=McAfee;i="6700,10204,11277"; a="33921137" X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="33921137" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:28 -0800 X-CSE-ConnectionGUID: YaD2eBlxQh2LzW5EpjezgA== X-CSE-MsgGUID: 3GbcJXqrRU2BNebIBZYSkQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="93905549" Received: from kcaccard-desk.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.125.108.178]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:28 -0800 Subject: [PATCH 02/11] coco/guest: Move shared guest CC infrastructure to drivers/virt/coco/guest/ From: Dan Williams To: linux-coco@lists.linux.dev Cc: Wu Hao , Yilun Xu , Samuel Ortiz , Alexey Kardashevskiy , Tom Lendacky , linux-pci@vger.kernel.org, gregkh@linuxfoundation.org Date: Thu, 05 Dec 2024 14:23:27 -0800 Message-ID: <173343740777.1074769.15850350070210009497.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> References: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In preparation for creating a new drivers/virt/coco/host/ directory to house shared host driver infrastructure for confidential computing, move configfs-tsm to a guest/ sub-directory. The tsm.ko module is renamed to tsm_reports.ko. The old tsm.ko module was only ever demand loaded by kernel internal dependencies, so it should not affect existing userspace module install scripts. The new drivers/virt/coco/guest/ is also a preparatory landing spot for new / optional TSM Report mechanics like a TCB stability enumeration / watchdog mechanism. To be added later. Cc: Wu Hao Cc: Yilun Xu Cc: Samuel Ortiz Cc: Alexey Kardashevskiy Cc: Tom Lendacky Signed-off-by: Dan Williams Reviewed-by: Alexey Kardashevskiy --- MAINTAINERS | 2 +- drivers/virt/coco/Kconfig | 6 ++---- drivers/virt/coco/Makefile | 2 +- drivers/virt/coco/guest/Kconfig | 7 +++++++ drivers/virt/coco/guest/Makefile | 3 +++ drivers/virt/coco/guest/report.c | 0 6 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 drivers/virt/coco/guest/Kconfig create mode 100644 drivers/virt/coco/guest/Makefile rename drivers/virt/coco/{tsm.c => guest/report.c} (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 53f04c499705..0c8f61662836 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23843,7 +23843,7 @@ M: Dan Williams L: linux-coco@lists.linux.dev S: Maintained F: Documentation/ABI/testing/configfs-tsm-report -F: drivers/virt/coco/tsm.c +F: drivers/virt/coco/guest/ F: include/linux/tsm.h TRUSTED SERVICES TEE DRIVER diff --git a/drivers/virt/coco/Kconfig b/drivers/virt/coco/Kconfig index ff869d883d95..819a97e8ba99 100644 --- a/drivers/virt/coco/Kconfig +++ b/drivers/virt/coco/Kconfig @@ -3,10 +3,6 @@ # Confidential computing related collateral # -config TSM_REPORTS - select CONFIGFS_FS - tristate - source "drivers/virt/coco/efi_secret/Kconfig" source "drivers/virt/coco/pkvm-guest/Kconfig" @@ -16,3 +12,5 @@ source "drivers/virt/coco/sev-guest/Kconfig" source "drivers/virt/coco/tdx-guest/Kconfig" source "drivers/virt/coco/arm-cca-guest/Kconfig" + +source "drivers/virt/coco/guest/Kconfig" diff --git a/drivers/virt/coco/Makefile b/drivers/virt/coco/Makefile index c3d07cfc087e..885c9ef4e9fc 100644 --- a/drivers/virt/coco/Makefile +++ b/drivers/virt/coco/Makefile @@ -2,9 +2,9 @@ # # Confidential computing related collateral # -obj-$(CONFIG_TSM_REPORTS) += tsm.o obj-$(CONFIG_EFI_SECRET) += efi_secret/ obj-$(CONFIG_ARM_PKVM_GUEST) += pkvm-guest/ obj-$(CONFIG_SEV_GUEST) += sev-guest/ obj-$(CONFIG_INTEL_TDX_GUEST) += tdx-guest/ obj-$(CONFIG_ARM_CCA_GUEST) += arm-cca-guest/ +obj-$(CONFIG_TSM_REPORTS) += guest/ diff --git a/drivers/virt/coco/guest/Kconfig b/drivers/virt/coco/guest/Kconfig new file mode 100644 index 000000000000..ed9bafbdd854 --- /dev/null +++ b/drivers/virt/coco/guest/Kconfig @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Confidential computing shared guest collateral +# +config TSM_REPORTS + select CONFIGFS_FS + tristate diff --git a/drivers/virt/coco/guest/Makefile b/drivers/virt/coco/guest/Makefile new file mode 100644 index 000000000000..b3b217af77cf --- /dev/null +++ b/drivers/virt/coco/guest/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_TSM_REPORTS) += tsm_report.o +tsm_report-y := report.o diff --git a/drivers/virt/coco/tsm.c b/drivers/virt/coco/guest/report.c similarity index 100% rename from drivers/virt/coco/tsm.c rename to drivers/virt/coco/guest/report.c From patchwork Thu Dec 5 22:23:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 13896043 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.18]) (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 4C9441C3C1F for ; Thu, 5 Dec 2024 22:23:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437417; cv=none; b=n8y2eY85SpBi6lJ6P4DK3H5M3q4PAdECOEhsfKwBn3lg18KEV7yYT/KRUx28AHY9/JM+TBD133MVwSSjBbB99v4LuYu0uXlg1MQ6vI5rBgkC/RLGpftNKucMezcrGnwl9Xy2quSyKIP1rnEwQPUo0c0D0HpJwo7+vhmhnNiiycY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437417; c=relaxed/simple; bh=x9R4We0vG84yE6SsKyj5bY0hN4eya1nRs07Q5rgSMsE=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=StBZGCo+eVjuveGNS01gaZAGX5PXhGT12WQdF9xwlwwWxQYoTOoyGEhinYe57JRD0oInHrRYqce7OLDiuelagBR4EfIkzuwR4oJqpt6p2XYRvLrjZswmeXy85DBQPp6O/7UItBmuqcDZGBDMheDfOir7m80Rh3l+kK4NR1q0IXM= ARC-Authentication-Results: i=1; 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=MhdobYQi; arc=none smtp.client-ip=198.175.65.18 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="MhdobYQi" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733437415; x=1764973415; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=x9R4We0vG84yE6SsKyj5bY0hN4eya1nRs07Q5rgSMsE=; b=MhdobYQiyifzkWvgBSqDNj+jYkDqRd/A1yb2wefM290Mn78orBXgGcDt ifDBwwIQdkEziC5TLOInHoH/k+LR4sg3BCP+EoPuLQEvuYWHsMsIkpQJj adbCsEh3510Q5dXHGBSiRIhIhHJYtFWb1w/VfOeDaDd9rL5a89OM3+pFH KnwWD7MmRYG+VjrMyXN5OtlKbWTs2Oikn4BIb/w5UzdxioilxebXeDgRw zvwlSwMq4MmtPsjLmWzQ1dQaseN/AZbgNHi4xzCq5dB4Cr4jAedrup93V c8SWe705OXglcuOUBEkEyxkgSQzWqE5MXGofoPmehjE9nhzAY81Av3t/C w==; X-CSE-ConnectionGUID: VnNtaP4sRK+Yu+HRIwVpZA== X-CSE-MsgGUID: 9cBgVCrtSyq4uhVGZphVVg== X-IronPort-AV: E=McAfee;i="6700,10204,11277"; a="33921140" X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="33921140" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:35 -0800 X-CSE-ConnectionGUID: u/fT3xYyS4as6CKj6zUaNw== X-CSE-MsgGUID: 8b1uCHtTTsm5XZBrH9rEFg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="93905577" Received: from kcaccard-desk.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.125.108.178]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:34 -0800 Subject: [PATCH 03/11] coco/tsm: Introduce a class device for TEE Security Managers From: Dan Williams To: linux-coco@lists.linux.dev Cc: Xiaoyao Li , Isaku Yamahata , Alexey Kardashevskiy , Yilun Xu , Tom Lendacky , John Allen , linux-pci@vger.kernel.org, gregkh@linuxfoundation.org Date: Thu, 05 Dec 2024 14:23:33 -0800 Message-ID: <173343741358.1074769.14824760616956254302.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> References: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 A "TSM" is a platform component that provides an API for securely provisioning resources for a confidential guest (TVM) to consume. The name originates from the PCI specification for platform agent that carries out operations for PCIe TDISP (TEE Device Interface Security Protocol). Instances of this class device are parented by a device representing the platform security capability like CONFIG_CRYPTO_DEV_CCP or CONFIG_INTEL_TDX_HOST. This class device interface is a frontend to the aspects of a TSM and TEE I/O that are cross-architecture common. This includes mechanisms like enumerating available platform TEE I/O capabilities and provisioning connections between the platform TSM and device DSMs (Device Security Manager (TDISP)). For now this is just the scaffolding for registering a TSM device sysfs interface. Cc: Xiaoyao Li Cc: Isaku Yamahata Cc: Alexey Kardashevskiy Cc: Yilun Xu Cc: Tom Lendacky Cc: John Allen Signed-off-by: Dan Williams --- Documentation/ABI/testing/sysfs-class-tsm | 10 +++ MAINTAINERS | 3 + drivers/virt/coco/Kconfig | 2 + drivers/virt/coco/Makefile | 1 drivers/virt/coco/host/Kconfig | 6 ++ drivers/virt/coco/host/Makefile | 6 ++ drivers/virt/coco/host/tsm-core.c | 113 +++++++++++++++++++++++++++++ include/linux/tsm.h | 5 + 8 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/sysfs-class-tsm create mode 100644 drivers/virt/coco/host/Kconfig create mode 100644 drivers/virt/coco/host/Makefile create mode 100644 drivers/virt/coco/host/tsm-core.c diff --git a/Documentation/ABI/testing/sysfs-class-tsm b/Documentation/ABI/testing/sysfs-class-tsm new file mode 100644 index 000000000000..7503f04a9eb9 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-tsm @@ -0,0 +1,10 @@ +What: /sys/class/tsm/tsm0 +Date: Dec, 2024 +Contact: linux-coco@lists.linux.dev +Description: + "tsm0" is a singleton device that represents the generic + attributes of a platform TEE Security Manager. It is a child of + the platform TSM device. /sys/class/tsm/tsm0/uevent + signals when the PCI layer is able to support establishment of + link encryption and other device-security features coordinated + through the platform tsm. diff --git a/MAINTAINERS b/MAINTAINERS index 0c8f61662836..abaabbc39134 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23838,12 +23838,13 @@ W: https://github.com/srcres258/linux-doc T: git git://github.com/srcres258/linux-doc.git doc-zh-tw F: Documentation/translations/zh_TW/ -TRUSTED SECURITY MODULE (TSM) ATTESTATION REPORTS +TRUSTED (TEE) SECURITY MANAGER (TSM) M: Dan Williams L: linux-coco@lists.linux.dev S: Maintained F: Documentation/ABI/testing/configfs-tsm-report F: drivers/virt/coco/guest/ +F: drivers/virt/coco/host/ F: include/linux/tsm.h TRUSTED SERVICES TEE DRIVER diff --git a/drivers/virt/coco/Kconfig b/drivers/virt/coco/Kconfig index 819a97e8ba99..14e7cf145d85 100644 --- a/drivers/virt/coco/Kconfig +++ b/drivers/virt/coco/Kconfig @@ -14,3 +14,5 @@ source "drivers/virt/coco/tdx-guest/Kconfig" source "drivers/virt/coco/arm-cca-guest/Kconfig" source "drivers/virt/coco/guest/Kconfig" + +source "drivers/virt/coco/host/Kconfig" diff --git a/drivers/virt/coco/Makefile b/drivers/virt/coco/Makefile index 885c9ef4e9fc..73f1b7bc5b11 100644 --- a/drivers/virt/coco/Makefile +++ b/drivers/virt/coco/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_SEV_GUEST) += sev-guest/ obj-$(CONFIG_INTEL_TDX_GUEST) += tdx-guest/ obj-$(CONFIG_ARM_CCA_GUEST) += arm-cca-guest/ obj-$(CONFIG_TSM_REPORTS) += guest/ +obj-y += host/ diff --git a/drivers/virt/coco/host/Kconfig b/drivers/virt/coco/host/Kconfig new file mode 100644 index 000000000000..4fbc6ef34f12 --- /dev/null +++ b/drivers/virt/coco/host/Kconfig @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# TSM (TEE Security Manager) Common infrastructure and host drivers +# +config TSM + tristate diff --git a/drivers/virt/coco/host/Makefile b/drivers/virt/coco/host/Makefile new file mode 100644 index 000000000000..be0aba6007cd --- /dev/null +++ b/drivers/virt/coco/host/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# TSM (TEE Security Manager) Common infrastructure and host drivers + +obj-$(CONFIG_TSM) += tsm.o +tsm-y := tsm-core.o diff --git a/drivers/virt/coco/host/tsm-core.c b/drivers/virt/coco/host/tsm-core.c new file mode 100644 index 000000000000..0ee738fc40ed --- /dev/null +++ b/drivers/virt/coco/host/tsm-core.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2024 Intel Corporation. All rights reserved. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +static DECLARE_RWSEM(tsm_core_rwsem); +static struct class *tsm_class; +static struct tsm_subsys { + struct device dev; +} *tsm_subsys; + +static struct tsm_subsys * +alloc_tsm_subsys(struct device *parent, const struct attribute_group **groups) +{ + struct tsm_subsys *subsys = kzalloc(sizeof(*subsys), GFP_KERNEL); + struct device *dev; + + if (!subsys) + return ERR_PTR(-ENOMEM); + dev = &subsys->dev; + dev->parent = parent; + dev->groups = groups; + dev->class = tsm_class; + device_initialize(dev); + return subsys; +} + +static void put_tsm_subsys(struct tsm_subsys *subsys) +{ + if (!IS_ERR_OR_NULL(subsys)) + put_device(&subsys->dev); +} + +DEFINE_FREE(put_tsm_subsys, struct tsm_subsys *, + if (!IS_ERR_OR_NULL(_T)) put_tsm_subsys(_T)) +struct tsm_subsys *tsm_register(struct device *parent, + const struct attribute_group **groups) +{ + struct device *dev; + int rc; + + guard(rwsem_write)(&tsm_core_rwsem); + if (tsm_subsys) { + dev_warn(parent, "failed to register: %s already registered\n", + dev_name(tsm_subsys->dev.parent)); + return ERR_PTR(-EBUSY); + } + + struct tsm_subsys *subsys __free(put_tsm_subsys) = + alloc_tsm_subsys(parent, groups); + if (IS_ERR(subsys)) + return subsys; + + dev = &subsys->dev; + rc = dev_set_name(dev, "tsm0"); + if (rc) + return ERR_PTR(rc); + + rc = device_add(dev); + if (rc) + return ERR_PTR(rc); + + tsm_subsys = no_free_ptr(subsys); + + return tsm_subsys; +} +EXPORT_SYMBOL_GPL(tsm_register); + +void tsm_unregister(struct tsm_subsys *subsys) +{ + guard(rwsem_write)(&tsm_core_rwsem); + if (!tsm_subsys || subsys != tsm_subsys) { + pr_warn("failed to unregister, not currently registered\n"); + return; + } + + device_unregister(&subsys->dev); + tsm_subsys = NULL; +} +EXPORT_SYMBOL_GPL(tsm_unregister); + +static void tsm_release(struct device *dev) +{ + struct tsm_subsys *subsys = container_of(dev, typeof(*subsys), dev); + + kfree(subsys); +} + +static int __init tsm_init(void) +{ + tsm_class = class_create("tsm"); + if (IS_ERR(tsm_class)) + return PTR_ERR(tsm_class); + + tsm_class->dev_release = tsm_release; + return 0; +} +module_init(tsm_init) + +static void __exit tsm_exit(void) +{ + class_destroy(tsm_class); +} +module_exit(tsm_exit) + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("TEE Security Manager core"); diff --git a/include/linux/tsm.h b/include/linux/tsm.h index 431054810dca..1a97459fc23e 100644 --- a/include/linux/tsm.h +++ b/include/linux/tsm.h @@ -5,6 +5,7 @@ #include #include #include +#include #define TSM_REPORT_INBLOB_MAX 64 #define TSM_REPORT_OUTBLOB_MAX SZ_32K @@ -109,4 +110,8 @@ struct tsm_report_ops { int tsm_report_register(const struct tsm_report_ops *ops, void *priv); int tsm_report_unregister(const struct tsm_report_ops *ops); +struct tsm_subsys; +struct tsm_subsys *tsm_register(struct device *parent, + const struct attribute_group **groups); +void tsm_unregister(struct tsm_subsys *subsys); #endif /* __TSM_H */ From patchwork Thu Dec 5 22:23:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 13896044 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) (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 BAC0A1BD51B for ; Thu, 5 Dec 2024 22:23:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437422; cv=none; b=uooLE9PfNUTrFkgAw6W5IyCJ1bR15+VHpI9IF2pyUk1q23wf1Ze/xqGOJlcguOV/RF/DS5OLUjnzMKyDT/lPRQSVyf9Q59iqFAEElBAgDtSa7/w66oIXx6zj3/pei5iBO7KZem/WkY5e2W4xNJdA+b4rUFWVGSxDWEutEUYH6H0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437422; c=relaxed/simple; bh=uUq0/GOA1EQbKpjajAth6SoWrhAyqr+GIV7hcxMGeGk=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=RE4Vdu7v6GVCRCtkvLK9P9kIH/kMNDeYto6AK7R21iaWT3Dp1DtJ3Yi7rCVjeO1KEDUUlycb851RJzzc5Q1O/4Lqi4cRmK4be/Hc4mmzHfGOkFvw0280eUBIQxhESoZJ/uikhaZp8WDrzEDxf3AEGe5bcyp99EYeo5oTT1aHOPs= ARC-Authentication-Results: i=1; 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=fwBqvmnh; arc=none smtp.client-ip=198.175.65.16 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="fwBqvmnh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733437420; x=1764973420; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=uUq0/GOA1EQbKpjajAth6SoWrhAyqr+GIV7hcxMGeGk=; b=fwBqvmnhRK1lUk0odSgN9Q5DbR4HyarI8ahn6JmZlAAQ6mME79ZbqUir Mav+XqcsaYpX8CtbRJiamnw89Y80XLkrtiGLX4M+rA7jZa+9wOCmrBptU HGeJlNXFtI4VeOEmLsqdINvLEAtwkNWUvIN0C0D4q8JNTgJKSJThFiL1N e6hw7duZayGIzYv96NLyAxAkB0ZCERGIDtWrZ+PWsHWAwc2UNmfLohIMu 3fgNDzGEPOHKj4qw5cKznmQ16vXL4qEzghSXaZy7WOISE9hyk/IKgIhaQ yF2BgDQz6YBx9QgSU/Fibiv7mjROJcrf2yl5orGstUP0FJSdpueAcIG0g w==; X-CSE-ConnectionGUID: a1EG/HzjQEiqCaofJAgk4g== X-CSE-MsgGUID: 1nfvf0i1Su6cGfG/gv/iqA== X-IronPort-AV: E=McAfee;i="6700,10204,11277"; a="33910422" X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="33910422" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:40 -0800 X-CSE-ConnectionGUID: cKhNha+FQYOOgF+9Azue7Q== X-CSE-MsgGUID: XlG4EP+qTB6HU51wo31CWw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="99050093" Received: from kcaccard-desk.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.125.108.178]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:40 -0800 Subject: [PATCH 04/11] PCI/IDE: Selective Stream IDE enumeration From: Dan Williams To: linux-coco@lists.linux.dev Cc: Alexey Kardashevskiy , linux-pci@vger.kernel.org, gregkh@linuxfoundation.org Date: Thu, 05 Dec 2024 14:23:39 -0800 Message-ID: <173343741936.1074769.17093052628585780785.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> References: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Link encryption is a new PCIe capability defined by "PCIe 6.2 section 6.33 Integrity & Data Encryption (IDE)". While it is a standalone port and endpoint capability, it is also a building block for device security defined by "PCIe 6.2 section 11 TEE Device Interface Security Protocol (TDISP)". That protocol coordinates device security setup between the platform TSM (TEE Security Manager) and device DSM (Device Security Manager). While the platform TSM can allocate resources like stream-ids and manage keys, it still requires system software to manage the IDE capability register block. Add register definitions and basic enumeration for a "selective-stream" IDE capability, a follow on change will select the new CONFIG_PCI_IDE symbol. Note that while the IDE specifications defines both a point-to-point "Link" stream and a root-port-to-endpoint "Selective" stream, only "Selective" is considered for now for platform TSM coordination. Co-developed-by: Alexey Kardashevskiy Signed-off-by: Alexey Kardashevskiy Signed-off-by: Dan Williams --- drivers/pci/Kconfig | 3 + drivers/pci/Makefile | 1 drivers/pci/ide.c | 73 ++++++++++++++++++++++++++++++++++++ drivers/pci/pci.h | 6 +++ drivers/pci/probe.c | 1 include/linux/pci.h | 5 ++ include/uapi/linux/pci_regs.h | 84 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 drivers/pci/ide.c diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 2fbd379923fd..4e5236c456f5 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -121,6 +121,9 @@ config XEN_PCIDEV_FRONTEND config PCI_ATS bool +config PCI_IDE + bool + config PCI_DOE bool diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 67647f1880fb..6612256fd37d 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_PCI_P2PDMA) += p2pdma.o obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o obj-$(CONFIG_VGA_ARB) += vgaarb.o obj-$(CONFIG_PCI_DOE) += doe.o +obj-$(CONFIG_PCI_IDE) += ide.o obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) += of_property.o obj-$(CONFIG_PCI_NPEM) += npem.o obj-$(CONFIG_PCIE_TPH) += tph.o diff --git a/drivers/pci/ide.c b/drivers/pci/ide.c new file mode 100644 index 000000000000..a0c09d9e0b75 --- /dev/null +++ b/drivers/pci/ide.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2024 Intel Corporation. All rights reserved. */ + +/* PCIe 6.2 section 6.33 Integrity & Data Encryption (IDE) */ + +#define dev_fmt(fmt) "PCI/IDE: " fmt +#include +#include "pci.h" + +static int sel_ide_offset(u16 cap, int stream_id, int nr_ide_mem) +{ + return cap + stream_id * PCI_IDE_SELECTIVE_BLOCK_SIZE(nr_ide_mem); +} + +void pci_ide_init(struct pci_dev *pdev) +{ + u16 ide_cap, sel_ide_cap; + int nr_ide_mem = 0; + u32 val = 0; + + if (!pci_is_pcie(pdev)) + return; + + ide_cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_IDE); + if (!ide_cap) + return; + + /* + * Check for selective stream capability from endpoint to root-port, and + * require consistent number of address association blocks + */ + pci_read_config_dword(pdev, ide_cap + PCI_IDE_CAP, &val); + if ((val & PCI_IDE_CAP_SELECTIVE) == 0) + return; + + if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ENDPOINT) { + struct pci_dev *rp = pcie_find_root_port(pdev); + + if (!rp->ide_cap) + return; + } + + if (val & PCI_IDE_CAP_LINK) + sel_ide_cap = ide_cap + PCI_IDE_LINK_STREAM + + (PCI_IDE_CAP_LINK_TC_NUM(val) + 1) * + PCI_IDE_LINK_BLOCK_SIZE; + else + sel_ide_cap = ide_cap + PCI_IDE_LINK_STREAM; + + for (int i = 0; i < PCI_IDE_CAP_SELECTIVE_STREAMS_NUM(val); i++) { + if (i == 0) { + pci_read_config_dword(pdev, sel_ide_cap, &val); + nr_ide_mem = PCI_IDE_SEL_CAP_ASSOC_NUM(val); + } else { + int offset = sel_ide_offset(sel_ide_cap, i, nr_ide_mem); + + pci_read_config_dword(pdev, offset, &val); + + /* + * lets not entertain devices that do not have a + * constant number of address association blocks + */ + if (PCI_IDE_SEL_CAP_ASSOC_NUM(val) != nr_ide_mem) { + pci_info(pdev, "Unsupported Selective Stream %d capability\n", i); + return; + } + } + } + + pdev->ide_cap = ide_cap; + pdev->sel_ide_cap = sel_ide_cap; + pdev->nr_ide_mem = nr_ide_mem; +} diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 2e40fc63ba31..0305f497b28a 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -452,6 +452,12 @@ static inline void pci_npem_create(struct pci_dev *dev) { } static inline void pci_npem_remove(struct pci_dev *dev) { } #endif +#ifdef CONFIG_PCI_IDE +void pci_ide_init(struct pci_dev *dev); +#else +static inline void pci_ide_init(struct pci_dev *dev) { } +#endif + /** * pci_dev_set_io_state - Set the new error state if possible. * diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2e81ab0f5a25..e22f515a8da9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2517,6 +2517,7 @@ static void pci_init_capabilities(struct pci_dev *dev) pci_rcec_init(dev); /* Root Complex Event Collector */ pci_doe_init(dev); /* Data Object Exchange */ pci_tph_init(dev); /* TLP Processing Hints */ + pci_ide_init(dev); /* Link Integrity and Data Encryption */ pcie_report_downtraining(dev); pci_init_reset_methods(dev); diff --git a/include/linux/pci.h b/include/linux/pci.h index db9b47ce3eef..50811b7655dd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -530,6 +530,11 @@ struct pci_dev { #endif #ifdef CONFIG_PCI_NPEM struct npem *npem; /* Native PCIe Enclosure Management */ +#endif +#ifdef CONFIG_PCI_IDE + u16 ide_cap; /* Link Integrity & Data Encryption */ + u16 sel_ide_cap; /* - Selective Stream register block */ + int nr_ide_mem; /* - Address range limits for streams */ #endif u16 acs_cap; /* ACS Capability offset */ u8 supported_speeds; /* Supported Link Speeds Vector */ diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 1601c7ed5fab..9635b27d2485 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -748,7 +748,8 @@ #define PCI_EXT_CAP_ID_NPEM 0x29 /* Native PCIe Enclosure Management */ #define PCI_EXT_CAP_ID_PL_32GT 0x2A /* Physical Layer 32.0 GT/s */ #define PCI_EXT_CAP_ID_DOE 0x2E /* Data Object Exchange */ -#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DOE +#define PCI_EXT_CAP_ID_IDE 0x30 /* Integrity and Data Encryption */ +#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_IDE #define PCI_EXT_CAP_DSN_SIZEOF 12 #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 @@ -1213,4 +1214,85 @@ #define PCI_DVSEC_CXL_PORT_CTL 0x0c #define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR 0x00000001 +/* Integrity and Data Encryption Extended Capability */ +#define PCI_IDE_CAP 0x4 +#define PCI_IDE_CAP_LINK 0x1 /* Link IDE Stream Supported */ +#define PCI_IDE_CAP_SELECTIVE 0x2 /* Selective IDE Streams Supported */ +#define PCI_IDE_CAP_FLOWTHROUGH 0x4 /* Flow-Through IDE Stream Supported */ +#define PCI_IDE_CAP_PARTIAL_HEADER_ENC 0x8 /* Partial Header Encryption Supported */ +#define PCI_IDE_CAP_AGGREGATION 0x10 /* Aggregation Supported */ +#define PCI_IDE_CAP_PCRC 0x20 /* PCRC Supported */ +#define PCI_IDE_CAP_IDE_KM 0x40 /* IDE_KM Protocol Supported */ +#define PCI_IDE_CAP_ALG(x) (((x) >> 8) & 0x1f) /* Supported Algorithms */ +#define PCI_IDE_CAP_ALG_AES_GCM_256 0 /* AES-GCM 256 key size, 96b MAC */ +#define PCI_IDE_CAP_LINK_TC_NUM(x) (((x) >> 13) & 0x7) /* Link IDE TCs */ +#define PCI_IDE_CAP_SELECTIVE_STREAMS_NUM(x) (((x) >> 16) & 0xff) /* Selective IDE Streams */ +#define PCI_IDE_CAP_SELECTIVE_STREAMS_MASK 0xff0000 +#define PCI_IDE_CAP_TEE_LIMITED 0x1000000 /* TEE-Limited Stream Supported */ +#define PCI_IDE_CTL 0x8 +#define PCI_IDE_CTL_FLOWTHROUGH_IDE 0x4 /* Flow-Through IDE Stream Enabled */ +#define PCI_IDE_LINK_STREAM 0xc +#define PCI_IDE_LINK_BLOCK_SIZE 8 +/* Link IDE Stream block, up to PCI_IDE_CAP_LINK_TC_NUM */ +/* Link IDE Stream Control Register */ +#define PCI_IDE_LINK_CTL_EN 0x1 /* Link IDE Stream Enable */ +#define PCI_IDE_LINK_CTL_TX_AGGR_NPR(x) (((x) >> 2) & 0x3) /* Tx Aggregation Mode NPR */ +#define PCI_IDE_LINK_CTL_TX_AGGR_PR(x) (((x) >> 4) & 0x3) /* Tx Aggregation Mode PR */ +#define PCI_IDE_LINK_CTL_TX_AGGR_CPL(x) (((x) >> 6) & 0x3) /* Tx Aggregation Mode CPL */ +#define PCI_IDE_LINK_CTL_PCRC_EN 0x100 /* PCRC Enable */ +#define PCI_IDE_LINK_CTL_PART_ENC(x) (((x) >> 10) & 0xf) /* Partial Header Encryption Mode */ +#define PCI_IDE_LINK_CTL_ALG(x) (((x) >> 14) & 0x1f) /* Selected Algorithm */ +#define PCI_IDE_LINK_CTL_TC(x) (((x) >> 19) & 0x7) /* Traffic Class */ +#define PCI_IDE_LINK_CTL_ID(x) (((x) >> 24) & 0xff) /* Stream ID */ +#define PCI_IDE_LINK_CTL_ID_MASK 0xff000000 + + +/* Link IDE Stream Status Register */ +#define PCI_IDE_LINK_STS_STATUS(x) ((x) & 0xf) /* Link IDE Stream State */ +#define PCI_IDE_LINK_STS_RECVD_INTEGRITY_CHECK 0x80000000 /* Received Integrity Check Fail Msg */ +/* Selective IDE Stream block, up to PCI_IDE_CAP_SELECTIVE_STREAMS_NUM */ +#define PCI_IDE_SELECTIVE_BLOCK_SIZE(x) (20 + 12 * (x)) +/* Selective IDE Stream Capability Register */ +#define PCI_IDE_SEL_CAP 0 +#define PCI_IDE_SEL_CAP_ASSOC_NUM(x) ((x) & 0xf) /* Address Association Register Blocks Number */ +#define PCI_IDE_SEL_CAP_ASSOC_MASK 0xf +/* Selective IDE Stream Control Register */ +#define PCI_IDE_SEL_CTL 4 +#define PCI_IDE_SEL_CTL_EN 0x1 /* Selective IDE Stream Enable */ +#define PCI_IDE_SEL_CTL_TX_AGGR_NPR(x) (((x) >> 2) & 0x3) /* Tx Aggregation Mode NPR */ +#define PCI_IDE_SEL_CTL_TX_AGGR_PR(x) (((x) >> 4) & 0x3) /* Tx Aggregation Mode PR */ +#define PCI_IDE_SEL_CTL_TX_AGGR_CPL(x) (((x) >> 6) & 0x3) /* Tx Aggregation Mode CPL */ +#define PCI_IDE_SEL_CTL_PCRC_EN 0x100 /* PCRC Enable */ +#define PCI_IDE_SEL_CTL_CFG_EN 0x200 /* Selective IDE for Configuration Requests */ +#define PCI_IDE_SEL_CTL_PART_ENC(x) (((x) >> 10) & 0xf) /* Partial Header Encryption Mode */ +#define PCI_IDE_SEL_CTL_ALG(x) (((x) >> 14) & 0x1f) /* Selected Algorithm */ +#define PCI_IDE_SEL_CTL_TC(x) (((x) >> 19) & 0x7) /* Traffic Class */ +#define PCI_IDE_SEL_CTL_DEFAULT 0x400000 /* Default Stream */ +#define PCI_IDE_SEL_CTL_TEE_LIMITED (1 << 23) /* TEE-Limited Stream */ +#define PCI_IDE_SEL_CTL_ID_MASK 0xff000000 +#define PCI_IDE_SEL_CTL_ID_MAX 255 +/* Selective IDE Stream Status Register */ +#define PCI_IDE_SEL_STS 8 +#define PCI_IDE_SEL_STS_STATUS(x) ((x) & 0xf) /* Selective IDE Stream State */ +#define PCI_IDE_SEL_STS_RECVD_INTEGRITY_CHECK 0x80000000 /* Received Integrity Check Fail Msg */ +/* IDE RID Association Register 1 */ +#define PCI_IDE_SEL_RID_1 12 +#define PCI_IDE_SEL_RID_1_LIMIT_MASK 0xffff00 +/* IDE RID Association Register 2 */ +#define PCI_IDE_SEL_RID_2 16 +#define PCI_IDE_SEL_RID_2_VALID 0x1 +#define PCI_IDE_SEL_RID_2_BASE_MASK 0x00ffff00 +#define PCI_IDE_SEL_RID_2_SEG_MASK 0xff000000 +/* Selective IDE Address Association Register Block, up to PCI_IDE_SEL_CAP_ASSOC_NUM */ +#define PCI_IDE_SEL_ADDR_1(x) (20 + (x) * 12) +#define PCI_IDE_SEL_ADDR_1_VALID 0x1 +#define PCI_IDE_SEL_ADDR_1_BASE_LOW_MASK 0x000fff0 +#define PCI_IDE_SEL_ADDR_1_BASE_LOW_SHIFT 20 +#define PCI_IDE_SEL_ADDR_1_LIMIT_LOW_MASK 0xfff0000 +#define PCI_IDE_SEL_ADDR_1_LIMIT_LOW_SHIFT 20 +/* IDE Address Association Register 2 is "Memory Limit Upper" */ +/* IDE Address Association Register 3 is "Memory Base Upper" */ +#define PCI_IDE_SEL_ADDR_2(x) (24 + (x) * 12) +#define PCI_IDE_SEL_ADDR_3(x) (28 + (x) * 12) + #endif /* LINUX_PCI_REGS_H */ From patchwork Thu Dec 5 22:23:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 13896045 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) (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 5A4B01BD51B for ; Thu, 5 Dec 2024 22:23:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437429; cv=none; b=jG4ZIltNIW3V3BmQuAIjfQuxGmqIKEbXeoBA3GgiTIWQ4YLyKG2rMw2SIRVS2L5UW3VYQN8O6WX0B/hUO4ewDDEiQIEesscDKVYBeY7iKLApuSn1FVjsaeQbOJ/x4EWRzVlwFfxl9tR7V/BuXIVN0A99uRu0c0htDXdhZxrgLbg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437429; c=relaxed/simple; bh=s83znvCCdyPsJGiEyhNe920jmeWVFlyUg0yIpNWdDCk=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kwvUs5ygFV4vgLYLdWqgTFnCoezzrB/Tpy7b3wp1xspX/2ZgwurSn7CL1mcwKmczEy02aRna/FYylrIoLHC8g9Sh5ZRL0xSg7b+xVJWJ5YLOeoDH78R5dvhACAx/JgbYkq00ufFFlF88ClV/WGHBZ7I0KYLiJf+sdlzxJEdHdf0= ARC-Authentication-Results: i=1; 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=L2mj0HjN; arc=none smtp.client-ip=198.175.65.16 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="L2mj0HjN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733437426; x=1764973426; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=s83znvCCdyPsJGiEyhNe920jmeWVFlyUg0yIpNWdDCk=; b=L2mj0HjNB3JV2J3gNZy39RnVgQXrkYgAQUcVcHuUE/4r/Y0VFQdT/xpX 7oni/huoENWDEXp0AQ3+CoNJo8Kyr7TNBo3CS7rNjQ3hprTjDeEkvUWNB dAEPt7SsZ9uNnIx186TIaNVCTcXD1RldZrzK02thvBiFqTsoV0HqpqXv3 NwC40/v6s9RdTH+x0co447NVT5lLzsA/uH4ZSu+uYXAHWbId0RZT7d1Vi Od07IWk1FB/aeXb72Yo5z2e6kNY33KPtFuxwlQzPfB+SEyDAOJ0y4uYl7 wQXN+gwqEEaj8SUqHX66ubMu2rlrDHndxPVEw/daLauBaR/e2PO+mMfZt A==; X-CSE-ConnectionGUID: hGdSZD7eSgeNVQIpazPtyg== X-CSE-MsgGUID: pTxQG9c0QYuklDesWlXvSw== X-IronPort-AV: E=McAfee;i="6700,10204,11277"; a="33910429" X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="33910429" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:46 -0800 X-CSE-ConnectionGUID: p0naw/WCS5isAIIdkEXeAA== X-CSE-MsgGUID: P2anh6pIQ4OcU7aRWgcUyA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="99050126" Received: from kcaccard-desk.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.125.108.178]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:46 -0800 Subject: [PATCH 05/11] PCI/TSM: Authenticate devices via platform TSM From: Dan Williams To: linux-coco@lists.linux.dev Cc: Lukas Wunner , Samuel Ortiz , Alexey Kardashevskiy , Bjorn Helgaas , Xu Yilun , linux-pci@vger.kernel.org, gregkh@linuxfoundation.org Date: Thu, 05 Dec 2024 14:23:45 -0800 Message-ID: <173343742510.1074769.16552514658771224955.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> References: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The PCIe 6.1 specification, section 11, introduces the Trusted Execution Environment (TEE) Device Interface Security Protocol (TDISP). This interface definition builds upon Component Measurement and Authentication (CMA), and link Integrity and Data Encryption (IDE). It adds support for assigning devices (PCI physical or virtual function) to a confidential VM such that the assigned device is enabled to access guest private memory protected by technologies like Intel TDX, AMD SEV-SNP, RISCV COVE, or ARM CCA. The "TSM" (TEE Security Manager) is a concept in the TDISP specification of an agent that mediates between a "DSM" (Device Security Manager) and system software in both a VMM and a confidential VM. A VMM uses TSM ABIs to setup link security and assign devices. A confidential VM uses TSM ABIs to transition an assigned device into the TDISP "RUN" state and validate its configuration. From a Linux perspective the TSM abstracts many of the details of TDISP, IDE, and CMA. Some of those details leak through at times, but for the most part TDISP is an internal implementation detail of the TSM. CONFIG_PCI_TSM adds an "authenticated" attribute and "tsm/" subdirectory to pci-sysfs. The work in progress CONFIG_PCI_CMA (software kernel-native PCI authentication) that can depend on a local to the PCI core implementation, CONFIG_PCI_TSM needs to be prepared for late loading of the platform TSM driver. Consider that the TSM driver may itself be a PCI driver. Userspace can watch /sys/class/tsm/tsm0/uevent to know when the PCI core has TSM services enabled. The common verbs that the low-level TSM drivers implement are defined by 'struct pci_tsm_ops'. For now only 'connect' and 'disconnect' are defined for secure session and IDE establishment. The 'probe' and 'remove' operations setup per-device context representing the device's security manager (DSM). Note that there is only one DSM expected per physical PCI function, and that coordinates a variable number of assignable interfaces to CVMs. The locking allows for multiple devices to be executing commands simultaneously, one outstanding command per-device and an rwsem flushes all in-flight commands when a TSM low-level driver/device is removed. Thanks to Wu Hao for his work on an early draft of this support. Cc: Lukas Wunner Cc: Samuel Ortiz Cc: Alexey Kardashevskiy Acked-by: Bjorn Helgaas Co-developed-by: Xu Yilun Signed-off-by: Xu Yilun Signed-off-by: Dan Williams --- Documentation/ABI/testing/sysfs-bus-pci | 42 ++++ MAINTAINERS | 2 drivers/pci/Kconfig | 13 + drivers/pci/Makefile | 1 drivers/pci/pci-sysfs.c | 4 drivers/pci/pci.h | 10 + drivers/pci/probe.c | 1 drivers/pci/remove.c | 3 drivers/pci/tsm.c | 293 +++++++++++++++++++++++++++++++ drivers/virt/coco/host/tsm-core.c | 19 ++ include/linux/pci-tsm.h | 83 +++++++++ include/linux/pci.h | 3 include/linux/tsm.h | 4 include/uapi/linux/pci_regs.h | 1 14 files changed, 476 insertions(+), 3 deletions(-) create mode 100644 drivers/pci/tsm.c create mode 100644 include/linux/pci-tsm.h diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci index 5da6a14dc326..0d742ef41aa7 100644 --- a/Documentation/ABI/testing/sysfs-bus-pci +++ b/Documentation/ABI/testing/sysfs-bus-pci @@ -583,3 +583,45 @@ Description: enclosure-specific indications "specific0" to "specific7", hence the corresponding led class devices are unavailable if the DSM interface is used. + +What: /sys/bus/pci/devices/.../tsm/ +Date: July 2024 +Contact: linux-coco@lists.linux.dev +Description: + This directory only appears if a physical device function supports + authentication (PCIe CMA-SPDM), interface security (PCIe TDISP), and is + accepted for secure operation by the platform TSM driver. This attribute + directory appears dynamically after the platform TSM driver loads. So, + only after the /sys/class/tsm/tsm0 device arrives can tools assume that + devices without a tsm/ attribute directory will never have one, before + that, the security capabilities of the device relative to the platform + TSM are unknown. See Documentation/ABI/testing/sysfs-class-tsm. + +What: /sys/bus/pci/devices/.../tsm/connect +Date: July 2024 +Contact: linux-coco@lists.linux.dev +Description: + (RW) Writing "1" to this file triggers the platform TSM (TEE Security + Manager) to establish a connection with the device. This typically + includes an SPDM (DMTF Security Protocols and Data Models) session over + PCIe DOE (Data Object Exchange) and may also include PCIe IDE (Integrity + and Data Encryption) establishment. + +What: /sys/bus/pci/devices/.../authenticated +Date: July 2024 +Contact: linux-pci@vger.kernel.org +Description: + When the device's tsm/ directory is present device + authentication (PCIe CMA-SPDM) and link encryption (PCIe IDE) + are handled by the platform TSM (TEE Security Manager). When the + tsm/ directory is not present this attribute reflects only the + native CMA-SPDM authentication state with the kernel's + certificate store. + + If the attribute is not present, it indicates that + authentication is unsupported by the device, or the TSM has no + available authentication methods for the device. + + When present and the tsm/ attribute directory is present, the + authenticated attribute is an alias for the device 'connect' + state. See the 'tsm/connect' attribute for more details. diff --git a/MAINTAINERS b/MAINTAINERS index abaabbc39134..8f28a2d9bbc6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23843,8 +23843,10 @@ M: Dan Williams L: linux-coco@lists.linux.dev S: Maintained F: Documentation/ABI/testing/configfs-tsm-report +F: drivers/pci/tsm.c F: drivers/virt/coco/guest/ F: drivers/virt/coco/host/ +F: include/linux/pci-tsm.h F: include/linux/tsm.h TRUSTED SERVICES TEE DRIVER diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 4e5236c456f5..8dab60dadb7d 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -124,6 +124,19 @@ config PCI_ATS config PCI_IDE bool +config PCI_TSM + bool "TEE Security Manager for PCI Device Security" + select PCI_IDE + help + The TEE (Trusted Execution Environment) Device Interface + Security Protocol (TDISP) defines a "TSM" as a platform agent + that manages device authentication, link encryption, link + integrity protection, and assignment of PCI device functions + (virtual or physical) to confidential computing VMs that can + access (DMA) guest private memory. + + Enable a platform TSM driver to use this capability. + config PCI_DOE bool diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 6612256fd37d..2c545f877062 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o obj-$(CONFIG_VGA_ARB) += vgaarb.o obj-$(CONFIG_PCI_DOE) += doe.o obj-$(CONFIG_PCI_IDE) += ide.o +obj-$(CONFIG_PCI_TSM) += tsm.o obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) += of_property.o obj-$(CONFIG_PCI_NPEM) += npem.o obj-$(CONFIG_PCIE_TPH) += tph.o diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 7679d75d71e5..7e1ed3440a50 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1696,6 +1696,10 @@ const struct attribute_group *pci_dev_attr_groups[] = { #endif #ifdef CONFIG_PCIEASPM &aspm_ctrl_attr_group, +#endif +#ifdef CONFIG_PCI_TSM + &pci_tsm_auth_attr_group, + &pci_tsm_attr_group, #endif NULL, }; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 0305f497b28a..0537fc72d5be 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -458,6 +458,16 @@ void pci_ide_init(struct pci_dev *dev); static inline void pci_ide_init(struct pci_dev *dev) { } #endif +#ifdef CONFIG_PCI_TSM +void pci_tsm_init(struct pci_dev *pdev); +void pci_tsm_destroy(struct pci_dev *pdev); +extern const struct attribute_group pci_tsm_attr_group; +extern const struct attribute_group pci_tsm_auth_attr_group; +#else +static inline void pci_tsm_init(struct pci_dev *pdev) { } +static inline void pci_tsm_destroy(struct pci_dev *pdev) { } +#endif + /** * pci_dev_set_io_state - Set the new error state if possible. * diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e22f515a8da9..7cddde3cb0ed 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2518,6 +2518,7 @@ static void pci_init_capabilities(struct pci_dev *dev) pci_doe_init(dev); /* Data Object Exchange */ pci_tph_init(dev); /* TLP Processing Hints */ pci_ide_init(dev); /* Link Integrity and Data Encryption */ + pci_tsm_init(dev); /* TEE Security Manager connection */ pcie_report_downtraining(dev); pci_init_reset_methods(dev); diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index efc37fcb73e2..fd4ccafed067 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -55,6 +55,9 @@ static void pci_destroy_dev(struct pci_dev *dev) pci_npem_remove(dev); + /* before device_del() to keep config cycle access */ + pci_tsm_destroy(dev); + device_del(&dev->dev); down_write(&pci_bus_sem); diff --git a/drivers/pci/tsm.c b/drivers/pci/tsm.c new file mode 100644 index 000000000000..04e9257a6e41 --- /dev/null +++ b/drivers/pci/tsm.c @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TEE Security Manager for the TEE Device Interface Security Protocol + * (TDISP, PCIe r6.1 sec 11) + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + */ + +#define dev_fmt(fmt) "TSM: " fmt + +#include +#include +#include +#include +#include +#include +#include "pci.h" + +/* + * Provide a read/write lock against the init / exit of pdev tsm + * capabilities and arrival/departure of a tsm instance + */ +static DECLARE_RWSEM(pci_tsm_rwsem); +static const struct pci_tsm_ops *tsm_ops; + +/* supplemental attributes to surface when pci_tsm_attr_group is active */ +static const struct attribute_group *pci_tsm_owner_attr_group; + +static int pci_tsm_disconnect(struct pci_dev *pdev) +{ + struct pci_tsm *pci_tsm = pdev->tsm; + + lockdep_assert_held(&pci_tsm_rwsem); + if_not_guard(mutex_intr, &pci_tsm->lock) + return -EINTR; + + if (pci_tsm->state < PCI_TSM_CONNECT) + return 0; + if (pci_tsm->state < PCI_TSM_INIT) + return -ENXIO; + + tsm_ops->disconnect(pdev); + pci_tsm->state = PCI_TSM_INIT; + + return 0; +} + +static int pci_tsm_connect(struct pci_dev *pdev) +{ + struct pci_tsm *pci_tsm = pdev->tsm; + int rc; + + lockdep_assert_held(&pci_tsm_rwsem); + if_not_guard(mutex_intr, &pci_tsm->lock) + return -EINTR; + + if (pci_tsm->state >= PCI_TSM_CONNECT) + return 0; + if (pci_tsm->state < PCI_TSM_INIT) + return -ENXIO; + + rc = tsm_ops->connect(pdev); + if (rc) + return rc; + pci_tsm->state = PCI_TSM_CONNECT; + return 0; +} + +static ssize_t connect_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + int rc; + bool connect; + struct pci_dev *pdev = to_pci_dev(dev); + + rc = kstrtobool(buf, &connect); + if (rc) + return rc; + + if_not_guard(rwsem_read_intr, &pci_tsm_rwsem) + return -EINTR; + + if (connect) + rc = pci_tsm_connect(pdev); + else + rc = pci_tsm_disconnect(pdev); + if (rc) + return rc; + return len; +} + +static ssize_t connect_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + if_not_guard(rwsem_read_intr, &pci_tsm_rwsem) + return -EINTR; + if (!pdev->tsm) + return -ENXIO; + return sysfs_emit(buf, "%d\n", pdev->tsm->state >= PCI_TSM_CONNECT); +} +static DEVICE_ATTR_RW(connect); + +static bool pci_tsm_group_visible(struct kobject *kobj) +{ + struct device *dev = kobj_to_dev(kobj); + struct pci_dev *pdev = to_pci_dev(dev); + + if (pdev->tsm) + return true; + return false; +} +DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(pci_tsm); + +static struct attribute *pci_tsm_attrs[] = { + &dev_attr_connect.attr, + NULL, +}; + +const struct attribute_group pci_tsm_attr_group = { + .name = "tsm", + .attrs = pci_tsm_attrs, + .is_visible = SYSFS_GROUP_VISIBLE(pci_tsm), +}; + +static ssize_t authenticated_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + /* + * When device authentication is TSM owned, 'authenticated' is + * identical to the connect state. + */ + return connect_show(dev, attr, buf); +} +static DEVICE_ATTR_RO(authenticated); + +static struct attribute *pci_tsm_auth_attrs[] = { + &dev_attr_authenticated.attr, + NULL, +}; + +const struct attribute_group pci_tsm_auth_attr_group = { + .attrs = pci_tsm_auth_attrs, + .is_visible = SYSFS_GROUP_VISIBLE(pci_tsm), +}; + +static void dsm_remove(struct pci_dsm *dsm) +{ + if (!dsm) + return; + tsm_ops->remove(dsm); +} +DEFINE_FREE(dsm_remove, struct pci_dsm *, if (_T) dsm_remove(_T)) + +static bool is_physical_endpoint(struct pci_dev *pdev) +{ + if (!pci_is_pcie(pdev)) + return false; + + if (pdev->is_virtfn) + return false; + + if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ENDPOINT) + return false; + + return true; +} + +static void __pci_tsm_init(struct pci_dev *pdev) +{ + bool tee_cap; + + if (!is_physical_endpoint(pdev)) + return; + + tee_cap = pdev->devcap & PCI_EXP_DEVCAP_TEE; + + if (!(pdev->ide_cap || tee_cap)) + return; + + lockdep_assert_held_write(&pci_tsm_rwsem); + if (!tsm_ops) + return; + + struct pci_tsm *pci_tsm __free(kfree) = kzalloc(sizeof(*pci_tsm), GFP_KERNEL); + if (!pci_tsm) + return; + + /* + * If a physical device has any security capabilities it may be + * a candidate to connect with the platform TSM + */ + struct pci_dsm *dsm __free(dsm_remove) = tsm_ops->probe(pdev); + + pci_dbg(pdev, "Device security capabilities detected (%s%s ), TSM %s\n", + pdev->ide_cap ? " ide" : "", tee_cap ? " tee" : "", + dsm ? "attach" : "skip"); + + if (!dsm) + return; + + mutex_init(&pci_tsm->lock); + pci_tsm->doe_mb = pci_find_doe_mailbox(pdev, PCI_VENDOR_ID_PCI_SIG, + PCI_DOE_PROTO_CMA); + if (!pci_tsm->doe_mb) { + pci_warn(pdev, "TSM init failure, no CMA mailbox\n"); + return; + } + + pci_tsm->state = PCI_TSM_INIT; + pci_tsm->dsm = no_free_ptr(dsm); + pdev->tsm = no_free_ptr(pci_tsm); + sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group); + sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group); + if (pci_tsm_owner_attr_group) + sysfs_merge_group(&pdev->dev.kobj, pci_tsm_owner_attr_group); +} + +void pci_tsm_init(struct pci_dev *pdev) +{ + guard(rwsem_write)(&pci_tsm_rwsem); + __pci_tsm_init(pdev); +} + +int pci_tsm_register(const struct pci_tsm_ops *ops, const struct attribute_group *grp) +{ + struct pci_dev *pdev = NULL; + + if (!ops) + return 0; + guard(rwsem_write)(&pci_tsm_rwsem); + if (tsm_ops) + return -EBUSY; + tsm_ops = ops; + pci_tsm_owner_attr_group = grp; + for_each_pci_dev(pdev) + __pci_tsm_init(pdev); + return 0; +} +EXPORT_SYMBOL_GPL(pci_tsm_register); + +static void __pci_tsm_destroy(struct pci_dev *pdev) +{ + struct pci_tsm *pci_tsm = pdev->tsm; + + if (!pci_tsm) + return; + + lockdep_assert_held_write(&pci_tsm_rwsem); + if (pci_tsm->state > PCI_TSM_INIT) + pci_tsm_disconnect(pdev); + tsm_ops->remove(pci_tsm->dsm); + pdev->tsm = NULL; + if (pci_tsm_owner_attr_group) + sysfs_unmerge_group(&pdev->dev.kobj, pci_tsm_owner_attr_group); + sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group); + sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group); + kfree(pci_tsm); +} + +void pci_tsm_destroy(struct pci_dev *pdev) +{ + guard(rwsem_write)(&pci_tsm_rwsem); + __pci_tsm_destroy(pdev); +} + +void pci_tsm_unregister(const struct pci_tsm_ops *ops) +{ + struct pci_dev *pdev = NULL; + + if (!ops) + return; + guard(rwsem_write)(&pci_tsm_rwsem); + if (ops != tsm_ops) + return; + for_each_pci_dev(pdev) + __pci_tsm_destroy(pdev); + tsm_ops = NULL; +} +EXPORT_SYMBOL_GPL(pci_tsm_unregister); + +int pci_tsm_doe_transfer(struct pci_dev *pdev, enum pci_doe_proto type, + const void *req, size_t req_sz, void *resp, + size_t resp_sz) +{ + if (!pdev->tsm || !pdev->tsm->doe_mb) + return -ENXIO; + + return pci_doe(pdev->tsm->doe_mb, PCI_VENDOR_ID_PCI_SIG, type, req, + req_sz, resp, resp_sz); +} +EXPORT_SYMBOL_GPL(pci_tsm_doe_transfer); diff --git a/drivers/virt/coco/host/tsm-core.c b/drivers/virt/coco/host/tsm-core.c index 0ee738fc40ed..21270210b03f 100644 --- a/drivers/virt/coco/host/tsm-core.c +++ b/drivers/virt/coco/host/tsm-core.c @@ -8,11 +8,13 @@ #include #include #include +#include static DECLARE_RWSEM(tsm_core_rwsem); static struct class *tsm_class; static struct tsm_subsys { struct device dev; + const struct pci_tsm_ops *pci_ops; } *tsm_subsys; static struct tsm_subsys * @@ -40,7 +42,8 @@ static void put_tsm_subsys(struct tsm_subsys *subsys) DEFINE_FREE(put_tsm_subsys, struct tsm_subsys *, if (!IS_ERR_OR_NULL(_T)) put_tsm_subsys(_T)) struct tsm_subsys *tsm_register(struct device *parent, - const struct attribute_group **groups) + const struct attribute_group **groups, + const struct pci_tsm_ops *pci_ops) { struct device *dev; int rc; @@ -62,10 +65,20 @@ struct tsm_subsys *tsm_register(struct device *parent, if (rc) return ERR_PTR(rc); + rc = pci_tsm_register(pci_ops, NULL); + if (rc) { + dev_err(parent, "PCI initialization failure: %pe\n", + ERR_PTR(rc)); + return ERR_PTR(rc); + } + rc = device_add(dev); - if (rc) + if (rc) { + pci_tsm_unregister(pci_ops); return ERR_PTR(rc); + } + subsys->pci_ops = pci_ops; tsm_subsys = no_free_ptr(subsys); return tsm_subsys; @@ -80,7 +93,9 @@ void tsm_unregister(struct tsm_subsys *subsys) return; } + pci_tsm_unregister(subsys->pci_ops); device_unregister(&subsys->dev); + tsm_subsys = NULL; } EXPORT_SYMBOL_GPL(tsm_unregister); diff --git a/include/linux/pci-tsm.h b/include/linux/pci-tsm.h new file mode 100644 index 000000000000..beb0d68129bc --- /dev/null +++ b/include/linux/pci-tsm.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PCI_TSM_H +#define __PCI_TSM_H +#include + +struct pci_dev; + +/** + * struct pci_dsm - Device Security Manager context + * @pdev: physical device back pointer + */ +struct pci_dsm { + struct pci_dev *pdev; +}; + +enum pci_tsm_state { + PCI_TSM_ERR = -1, + PCI_TSM_INIT, + PCI_TSM_CONNECT, +}; + +/** + * struct pci_tsm - Platform TSM transport context + * @state: reflect device initialized, connected, or bound + * @lock: protect @state vs pci_tsm_ops invocation + * @doe_mb: PCIe Data Object Exchange mailbox + * @dsm: TSM driver device context established by pci_tsm_ops.probe + */ +struct pci_tsm { + enum pci_tsm_state state; + struct mutex lock; + struct pci_doe_mb *doe_mb; + struct pci_dsm *dsm; +}; + +/** + * struct pci_tsm_ops - Low-level TSM-exported interface to the PCI core + * @probe: probe/accept device for tsm operation, setup DSM context + * @remove: destroy DSM context + * @connect: establish / validate a secure connection (e.g. IDE) with the device + * @disconnect: teardown the secure connection + * + * @probe and @remove run in pci_tsm_rwsem held for write context. All + * other ops run under the @pdev->tsm->lock mutex and pci_tsm_rwsem held + * for read. + */ +struct pci_tsm_ops { + struct pci_dsm *(*probe)(struct pci_dev *pdev); + void (*remove)(struct pci_dsm *dsm); + int (*connect)(struct pci_dev *pdev); + void (*disconnect)(struct pci_dev *pdev); +}; + +enum pci_doe_proto { + PCI_DOE_PROTO_CMA = 1, + PCI_DOE_PROTO_SSESSION = 2, +}; + +#ifdef CONFIG_PCI_TSM +int pci_tsm_register(const struct pci_tsm_ops *ops, + const struct attribute_group *grp); +void pci_tsm_unregister(const struct pci_tsm_ops *ops); +int pci_tsm_doe_transfer(struct pci_dev *pdev, enum pci_doe_proto type, + const void *req, size_t req_sz, void *resp, + size_t resp_sz); +#else +static inline int pci_tsm_register(const struct pci_tsm_ops *ops, + const struct attribute_group *grp) +{ + return 0; +} +static inline void pci_tsm_unregister(const struct pci_tsm_ops *ops) +{ +} +static inline int pci_tsm_doe_transfer(struct pci_dev *pdev, + enum pci_doe_proto type, const void *req, + size_t req_sz, void *resp, + size_t resp_sz) +{ + return -ENOENT; +} +#endif +#endif /*__PCI_TSM_H */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 50811b7655dd..a0900e7d2012 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -535,6 +535,9 @@ struct pci_dev { u16 ide_cap; /* Link Integrity & Data Encryption */ u16 sel_ide_cap; /* - Selective Stream register block */ int nr_ide_mem; /* - Address range limits for streams */ +#endif +#ifdef CONFIG_PCI_TSM + struct pci_tsm *tsm; /* TSM operation state */ #endif u16 acs_cap; /* ACS Capability offset */ u8 supported_speeds; /* Supported Link Speeds Vector */ diff --git a/include/linux/tsm.h b/include/linux/tsm.h index 1a97459fc23e..46b9a0c6ea4e 100644 --- a/include/linux/tsm.h +++ b/include/linux/tsm.h @@ -111,7 +111,9 @@ struct tsm_report_ops { int tsm_report_register(const struct tsm_report_ops *ops, void *priv); int tsm_report_unregister(const struct tsm_report_ops *ops); struct tsm_subsys; +struct pci_tsm_ops; struct tsm_subsys *tsm_register(struct device *parent, - const struct attribute_group **groups); + const struct attribute_group **groups, + const struct pci_tsm_ops *ops); void tsm_unregister(struct tsm_subsys *subsys); #endif /* __TSM_H */ diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 9635b27d2485..19bba65a262c 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -499,6 +499,7 @@ #define PCI_EXP_DEVCAP_PWR_VAL 0x03fc0000 /* Slot Power Limit Value */ #define PCI_EXP_DEVCAP_PWR_SCL 0x0c000000 /* Slot Power Limit Scale */ #define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */ +#define PCI_EXP_DEVCAP_TEE 0x40000000 /* TEE I/O (TDISP) Support */ #define PCI_EXP_DEVCTL 0x08 /* Device Control */ #define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */ #define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */ From patchwork Thu Dec 5 22:23:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 13896053 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) (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 2D5791C3C1F for ; Thu, 5 Dec 2024 22:23:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437434; cv=none; b=ug9NMPimxWs/ek0yNz20nmEjpB1jWrT7q2Hq3vq1nlN1LIyliE/Y0/RHOAU9eS19NlT/I0/UEJeYmPUYB1eLmm5TqNIluirok9e7w+QcNRmd4Elx3EmfUZxaV69QPolywtQp6H7626QwUbcYFxSd/nr5UPL65eiVxCQglRsq4kE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437434; c=relaxed/simple; bh=uHecfVPaOLaRsGOP2/OK7b0aURyas04W6K7zvYixjFk=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UvfKQIhS8UQYhR0mTxSDstA8pPfbfngvMMjIr4GLCAXDodaX4r20Otq1JwmOeayf37tXv1rcZoscPvmBuddJK3UR7hnEELtLZzckFEyxIYO4lZ+Io0gKqrofr59CWb46BmmSeXZ30kMCwxoPAFOI4CbG1NdNUapfd3Ms75mCLqs= ARC-Authentication-Results: i=1; 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=lXter7T3; arc=none smtp.client-ip=198.175.65.16 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="lXter7T3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733437432; x=1764973432; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=uHecfVPaOLaRsGOP2/OK7b0aURyas04W6K7zvYixjFk=; b=lXter7T31AZ0uu2IIRyhyDhWXSQG3XiJo56DEQy5/D914zVMquOhTMi/ 3TUmJ0M3p6FMRBshS9a29EqLoEDDvCXccHau7mNtt8TNAiN7tohgY3aXS UK4n0JA11eLu/hp1tBf3s/XdGk1i3B1c7YSuS0GVsXR6VqpjDoA5gJMai FM6p5yFfaf9bNKMsn5SoKTMKLEe21944vEJwRmsPULFDgE9dla49j8EYs N9qTOpd2+fyYv2iZrflo7LA7Gf9XaDToBy4ECbPBPZvS/gYIsoJ5Dgm1t aP/ZcXLTNxJgWHCsyf0sBgw9Zxuq2lnuzNkaHq0q8/FetjnYWascn7MPM Q==; X-CSE-ConnectionGUID: JTVj1pAHRXGqh/b9cSRCgg== X-CSE-MsgGUID: /drtfDNXRuagwCvp8Qf5ug== X-IronPort-AV: E=McAfee;i="6700,10204,11277"; a="33910437" X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="33910437" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:52 -0800 X-CSE-ConnectionGUID: ekrwlgpTSGq2cz/wt7BpFg== X-CSE-MsgGUID: hCKqd+lHTeKfwdeBZI4RiA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="99050136" Received: from kcaccard-desk.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.125.108.178]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:51 -0800 Subject: [PATCH 06/11] samples/devsec: PCI device-security bus / endpoint sample From: Dan Williams To: linux-coco@lists.linux.dev Cc: Bjorn Helgaas , Lukas Wunner , Samuel Ortiz , Alexey Kardashevskiy , Xu Yilun , linux-pci@vger.kernel.org, gregkh@linuxfoundation.org Date: Thu, 05 Dec 2024 14:23:51 -0800 Message-ID: <173343743095.1074769.17985181033044298157.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> References: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Establish just enough emulated PCI infrastructure to register a sample TSM (platform security manager) driver and have it discover an IDE + TEE (link encryption + device-interface security protocol (TDISP)) capable device. Use the existing a CONFIG_PCI_BRIDGE_EMUL to emulate an IDE capable root port, and open code the emulation of an endpoint device via simulated configuration cycle responses. The devsec_tsm driver responds to the PCI core TSM operations as if it successfully exercised the given interface security protocol message. The devsec_bus and devsec_tsm drivers can be loaded in either order to reflect cases like SEV-TIO where the TSM is PCI-device firmware, and cases like TDX Connect where the TSM is a software agent running on the host CPU. Follow-on patches add common code for TSM managed IDE establishment. For now, just successfully complete setup and teardown of the DSM (device security manager) context as a building block for management of TDI (trusted device interface) instances. # modprobe devsec_bus devsec_bus devsec_bus: PCI host bridge to bus 10000:00 pci_bus 10000:00: root bus resource [bus 00-01] pci_bus 10000:00: root bus resource [mem 0xf000000000-0xffffffffff 64bit] pci 10000:00:00.0: [8086:7075] type 01 class 0x060400 PCIe Root Port pci 10000:00:00.0: PCI bridge to [bus 00] pci 10000:00:00.0: bridge window [io 0x0000-0x0fff] pci 10000:00:00.0: bridge window [mem 0x00000000-0x000fffff] pci 10000:00:00.0: bridge window [mem 0x00000000-0x000fffff 64bit pref] pci 10000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring pci 10000:01:00.0: [8086:ffff] type 00 class 0x000000 PCIe Endpoint pci 10000:01:00.0: BAR 0 [mem 0xf000000000-0xf0001fffff 64bit pref] pci_doe_abort: pci 10000:01:00.0: DOE: [100] Issuing Abort pci_doe_cache_protocols: pci 10000:01:00.0: DOE: [100] Found protocol 0 vid: 1 prot: 1 pci 10000:01:00.0: disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force' pci 10000:00:00.0: PCI bridge to [bus 01] pci_bus 10000:01: busn_res: [bus 01] end is updated to 01 # modprobe devsec_tsm devsec_tsm_pci_probe: pci 10000:01:00.0: devsec: tsm enabled __pci_tsm_init: pci 10000:01:00.0: TSM: Device security capabilities detected ( ide tee ), TSM attach Cc: Bjorn Helgaas Cc: Lukas Wunner Cc: Samuel Ortiz Cc: Alexey Kardashevskiy Cc: Xu Yilun Signed-off-by: Dan Williams --- MAINTAINERS | 1 samples/Kconfig | 15 + samples/Makefile | 1 samples/devsec/Makefile | 10 + samples/devsec/bus.c | 695 +++++++++++++++++++++++++++++++++++++++++++++++ samples/devsec/common.c | 26 ++ samples/devsec/devsec.h | 7 samples/devsec/tsm.c | 113 ++++++++ 8 files changed, 868 insertions(+) create mode 100644 samples/devsec/Makefile create mode 100644 samples/devsec/bus.c create mode 100644 samples/devsec/common.c create mode 100644 samples/devsec/devsec.h create mode 100644 samples/devsec/tsm.c diff --git a/MAINTAINERS b/MAINTAINERS index 8f28a2d9bbc6..9dba89d42af6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23848,6 +23848,7 @@ F: drivers/virt/coco/guest/ F: drivers/virt/coco/host/ F: include/linux/pci-tsm.h F: include/linux/tsm.h +F: samples/devsec/ TRUSTED SERVICES TEE DRIVER M: Balint Dobszay diff --git a/samples/Kconfig b/samples/Kconfig index b288d9991d27..9581757bfa67 100644 --- a/samples/Kconfig +++ b/samples/Kconfig @@ -293,6 +293,21 @@ config SAMPLE_CGROUP source "samples/rust/Kconfig" +config SAMPLE_DEVSEC + tristate "Build a sample TEE Security Manager with an emulated PCI endpoint" + depends on PCI + depends on X86 # missing PCI_DOMAINS_GENERIC support + select PCI_BRIDGE_EMUL + select PCI_TSM + select TSM + help + Build a sample platform TEE Security Manager (TSM) driver with a + corresponding emulated PCIe topology. The resulting sample modules, + devsec_bus and devsec_tsm, exercise device-security enumeration, PCI + subsystem use ABIs, device security flows. For example, exercise IDE + (link encryption) establishment and TDISP state transitions via a + Device Security Manager (DSM). + endif # SAMPLES config HAVE_SAMPLE_FTRACE_DIRECT diff --git a/samples/Makefile b/samples/Makefile index b85fa64390c5..da1829049249 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -39,3 +39,4 @@ obj-$(CONFIG_SAMPLE_KMEMLEAK) += kmemleak/ obj-$(CONFIG_SAMPLE_CORESIGHT_SYSCFG) += coresight/ obj-$(CONFIG_SAMPLE_FPROBE) += fprobe/ obj-$(CONFIG_SAMPLES_RUST) += rust/ +obj-y += devsec/ diff --git a/samples/devsec/Makefile b/samples/devsec/Makefile new file mode 100644 index 000000000000..c8cb5c0cceb8 --- /dev/null +++ b/samples/devsec/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_SAMPLE_DEVSEC) += devsec_common.o +devsec_common-y := common.o + +obj-$(CONFIG_SAMPLE_DEVSEC) += devsec_bus.o +devsec_bus-y := bus.o + +obj-$(CONFIG_SAMPLE_DEVSEC) += devsec_tsm.o +devsec_tsm-y := tsm.o diff --git a/samples/devsec/bus.c b/samples/devsec/bus.c new file mode 100644 index 000000000000..47dbe4e1b648 --- /dev/null +++ b/samples/devsec/bus.c @@ -0,0 +1,695 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2024 Intel Corporation. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../drivers/pci/pci-bridge-emul.h" +#include "devsec.h" + +#define NR_DEVSEC_BUSES 1 +#define NR_DEVSEC_ROOT_PORTS 1 +#define NR_STREAMS 1 +#define NR_ADDR_ASSOC 1 +#define NR_DEVSEC_DEVS 1 + +struct devsec { + struct pci_sysdata sysdata; + struct gen_pool *iomem_pool; + struct resource resource[2]; + struct pci_bus *bus; + struct device *dev; + struct devsec_port { + union { + struct devsec_ide { + u32 cap; + u32 ctl; + struct devsec_stream { + u32 cap; + u32 ctl; + u32 status; + u32 rid1; + u32 rid2; + struct devsec_addr_assoc { + u32 assoc1; + u32 assoc2; + u32 assoc3; + } assoc[NR_ADDR_ASSOC]; + } stream[NR_STREAMS]; + } ide __packed; + char ide_regs[sizeof(struct devsec_ide)]; + }; + struct pci_bridge_emul bridge; + } *devsec_ports[NR_DEVSEC_ROOT_PORTS]; + struct devsec_dev { + struct range mmio_range; + u8 __cfg[SZ_4K]; + struct devsec_dev_doe { + int cap; + u32 req[SZ_4K / sizeof(u32)]; + u32 rsp[SZ_4K / sizeof(u32)]; + int write, read, read_ttl; + } doe; + u16 ide_pos; + union { + struct devsec_ide ide __packed; + char ide_regs[sizeof(struct devsec_ide)]; + }; + } *devsec_devs[NR_DEVSEC_DEVS]; +}; + +#define devsec_base(x) ((void __force __iomem *) &(x)->__cfg[0]) + +static struct devsec *bus_to_devsec(struct pci_bus *bus) +{ + return container_of(bus->sysdata, struct devsec, sysdata); +} + +static int devsec_dev_config_read(struct devsec *devsec, struct pci_bus *bus, + unsigned int devfn, int pos, int size, + u32 *val) +{ + struct devsec_dev *devsec_dev; + struct devsec_dev_doe *doe; + void __iomem *base; + + if (PCI_FUNC(devfn) != 0 || + PCI_SLOT(devfn) >= ARRAY_SIZE(devsec->devsec_devs)) + return PCIBIOS_DEVICE_NOT_FOUND; + + devsec_dev = devsec->devsec_devs[PCI_SLOT(devfn)]; + base = devsec_base(devsec_dev); + doe = &devsec_dev->doe; + + if (pos == doe->cap + PCI_DOE_READ) { + if (doe->read_ttl > 0) { + *val = doe->rsp[doe->read]; + dev_dbg(&bus->dev, "devfn: %#x doe read[%d]\n", devfn, + doe->read); + } else { + *val = 0; + dev_dbg(&bus->dev, "devfn: %#x doe no data\n", devfn); + } + return PCIBIOS_SUCCESSFUL; + } else if (pos == doe->cap + PCI_DOE_STATUS) { + if (doe->read_ttl > 0) { + *val = PCI_DOE_STATUS_DATA_OBJECT_READY; + dev_dbg(&bus->dev, "devfn: %#x object ready\n", devfn); + } else if (doe->read_ttl < 0) { + *val = PCI_DOE_STATUS_ERROR; + dev_dbg(&bus->dev, "devfn: %#x error\n", devfn); + } else { + *val = 0; + dev_dbg(&bus->dev, "devfn: %#x idle\n", devfn); + } + return PCIBIOS_SUCCESSFUL; + } else if (pos >= devsec_dev->ide_pos && + pos < devsec_dev->ide_pos + sizeof(struct devsec_ide)) { + *val = *(u32 *) &devsec_dev->ide_regs[pos - devsec_dev->ide_pos]; + return PCIBIOS_SUCCESSFUL; + } + + switch (size) { + case 1: + *val = readb(base + pos); + break; + case 2: + *val = readw(base + pos); + break; + case 4: + *val = readl(base + pos); + break; + default: + PCI_SET_ERROR_RESPONSE(val); + return PCIBIOS_BAD_REGISTER_NUMBER; + } + return PCIBIOS_SUCCESSFUL; +} + +static int devsec_port_config_read(struct devsec *devsec, unsigned int devfn, + int pos, int size, u32 *val) +{ + struct devsec_port *devsec_port; + + if (PCI_FUNC(devfn) != 0 || + PCI_SLOT(devfn) >= ARRAY_SIZE(devsec->devsec_ports)) + return PCIBIOS_DEVICE_NOT_FOUND; + + devsec_port = devsec->devsec_ports[PCI_SLOT(devfn)]; + return pci_bridge_emul_conf_read(&devsec_port->bridge, pos, size, val); +} + +static int devsec_pci_read(struct pci_bus *bus, unsigned int devfn, int pos, + int size, u32 *val) +{ + struct devsec *devsec = bus_to_devsec(bus); + + dev_vdbg(&bus->dev, "devfn: %#x pos: %#x size: %d\n", devfn, pos, size); + + if (bus == devsec->bus) + return devsec_port_config_read(devsec, devfn, pos, size, val); + else if (bus->parent == devsec->bus) + return devsec_dev_config_read(devsec, bus, devfn, pos, size, + val); + + return PCIBIOS_DEVICE_NOT_FOUND; +} + +#ifndef PCI_DOE_PROTOCOL_DISCOVERY +#define PCI_DOE_PROTOCOL_DISCOVERY 0 +#define PCI_DOE_FEATURE_CMA 1 +#endif + +/* just indicate support for CMA */ +static void doe_process(struct devsec_dev_doe *doe) +{ + u8 type, index; + u16 vid; + + vid = FIELD_GET(PCI_DOE_DATA_OBJECT_HEADER_1_VID, doe->req[0]); + type = FIELD_GET(PCI_DOE_DATA_OBJECT_HEADER_1_TYPE, doe->req[0]); + + if (vid != PCI_VENDOR_ID_PCI_SIG) { + doe->read_ttl = -1; + return; + } + + if (type != PCI_DOE_PROTOCOL_DISCOVERY) { + doe->read_ttl = -1; + return; + } + + index = FIELD_GET(PCI_DOE_DATA_OBJECT_DISC_REQ_3_INDEX, doe->req[2]); + + doe->rsp[0] = doe->req[0]; + doe->rsp[1] = FIELD_PREP(PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH, 3); + doe->read_ttl = 3; + doe->rsp[2] = FIELD_PREP(PCI_DOE_DATA_OBJECT_DISC_RSP_3_VID, + PCI_VENDOR_ID_PCI_SIG) | + FIELD_PREP(PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL, + PCI_DOE_FEATURE_CMA) | + FIELD_PREP(PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX, 0); +} + +static int devsec_dev_config_write(struct devsec *devsec, struct pci_bus *bus, + unsigned int devfn, int pos, int size, + u32 val) +{ + struct devsec_dev *devsec_dev; + struct devsec_dev_doe *doe; + void __iomem *base; + + dev_vdbg(&bus->dev, "devfn: %#x pos: %#x size: %d\n", devfn, pos, size); + + if (PCI_FUNC(devfn) != 0 || + PCI_SLOT(devfn) >= ARRAY_SIZE(devsec->devsec_devs)) + return PCIBIOS_DEVICE_NOT_FOUND; + + devsec_dev = devsec->devsec_devs[PCI_SLOT(devfn)]; + base = devsec_base(devsec_dev); + doe = &devsec_dev->doe; + + if (pos >= PCI_BASE_ADDRESS_0 && pos <= PCI_BASE_ADDRESS_5) { + if (size != 4) + return PCIBIOS_BAD_REGISTER_NUMBER; + /* only one 64-bit mmio bar emulated for now */ + if (pos == PCI_BASE_ADDRESS_0) + val &= ~lower_32_bits(range_len(&devsec_dev->mmio_range) - 1); + else if (pos == PCI_BASE_ADDRESS_1) + val &= ~upper_32_bits(range_len(&devsec_dev->mmio_range) - 1); + else + val = 0; + } else if (pos == PCI_ROM_ADDRESS) { + val = 0; + } else if (pos == doe->cap + PCI_DOE_CTRL) { + if (val & PCI_DOE_CTRL_GO) { + dev_dbg(&bus->dev, "devfn: %#x doe go\n", devfn); + doe_process(doe); + } + if (val & PCI_DOE_CTRL_ABORT) { + dev_dbg(&bus->dev, "devfn: %#x doe abort\n", devfn); + doe->write = 0; + doe->read = 0; + doe->read_ttl = 0; + } + return PCIBIOS_SUCCESSFUL; + } else if (pos == doe->cap + PCI_DOE_WRITE) { + if (doe->write < ARRAY_SIZE(doe->req)) + doe->req[doe->write++] = val; + dev_dbg(&bus->dev, "devfn: %#x doe write[%d]\n", devfn, + doe->write - 1); + return PCIBIOS_SUCCESSFUL; + } else if (pos == doe->cap + PCI_DOE_READ) { + if (doe->read_ttl > 0) { + doe->read_ttl--; + doe->read++; + dev_dbg(&bus->dev, "devfn: %#x doe ack[%d]\n", devfn, + doe->read - 1); + } + return PCIBIOS_SUCCESSFUL; + } + + switch (size) { + case 1: + writeb(val, base + pos); + break; + case 2: + writew(val, base + pos); + break; + case 4: + writel(val, base + pos); + break; + default: + return PCIBIOS_BAD_REGISTER_NUMBER; + } + return PCIBIOS_SUCCESSFUL; +} + +static int devsec_port_config_write(struct devsec *devsec, struct pci_bus *bus, + unsigned int devfn, int pos, int size, + u32 val) +{ + struct devsec_port *devsec_port; + + dev_vdbg(&bus->dev, "devfn: %#x pos: %#x size: %d\n", devfn, pos, size); + + if (PCI_FUNC(devfn) != 0 || + PCI_SLOT(devfn) >= ARRAY_SIZE(devsec->devsec_ports)) + return PCIBIOS_DEVICE_NOT_FOUND; + + devsec_port = devsec->devsec_ports[PCI_SLOT(devfn)]; + return pci_bridge_emul_conf_write(&devsec_port->bridge, pos, size, val); +} + +static int devsec_pci_write(struct pci_bus *bus, unsigned int devfn, int pos, + int size, u32 val) +{ + struct devsec *devsec = bus_to_devsec(bus); + + dev_vdbg(&bus->dev, "devfn: %#x pos: %#x size: %d\n", devfn, pos, size); + + if (bus == devsec->bus) + return devsec_port_config_write(devsec, bus, devfn, pos, size, + val); + else if (bus->parent == devsec->bus) + return devsec_dev_config_write(devsec, bus, devfn, pos, size, + val); + return PCIBIOS_DEVICE_NOT_FOUND; +} + +static struct pci_ops devsec_ops = { + .read = devsec_pci_read, + .write = devsec_pci_write, +}; + +/* borrowed from vmd_find_free_domain() */ +static int find_free_domain(void) +{ + int domain = 0xffff; + struct pci_bus *bus = NULL; + + while ((bus = pci_find_next_bus(bus)) != NULL) + domain = max_t(int, domain, pci_domain_nr(bus)); + return domain + 1; +} + +static void destroy_iomem_pool(void *data) +{ + struct devsec *devsec = data; + + gen_pool_destroy(devsec->iomem_pool); +} + +static void destroy_bus(void *data) +{ + struct devsec *devsec = data; + + pci_stop_root_bus(devsec->bus); + pci_remove_root_bus(devsec->bus); +} + +static void destroy_devs(void *data) +{ + struct devsec *devsec = data; + int i; + + for (i = ARRAY_SIZE(devsec->devsec_devs) - 1; i >= 0; i--) { + struct devsec_dev *devsec_dev = devsec->devsec_devs[i]; + + if (!devsec_dev) + continue; + gen_pool_free(devsec->iomem_pool, devsec_dev->mmio_range.start, + range_len(&devsec_dev->mmio_range)); + kfree(devsec_dev); + devsec->devsec_devs[i] = NULL; + } +} + +static unsigned build_ext_cap_header(u32 id, u32 ver, u32 next) +{ + return FIELD_PREP(GENMASK(15, 0), id) | + FIELD_PREP(GENMASK(19, 16), ver) | + FIELD_PREP(GENMASK(31, 20), next); +} + +static void init_ide(struct devsec_ide *ide) +{ + ide->cap = PCI_IDE_CAP_SELECTIVE | PCI_IDE_CAP_IDE_KM | + PCI_IDE_CAP_TEE_LIMITED | + FIELD_PREP(PCI_IDE_CAP_SELECTIVE_STREAMS_MASK, NR_STREAMS); + + for (int i = 0; i < NR_STREAMS; i++) + ide->stream[i].cap = + FIELD_PREP(PCI_IDE_SEL_CAP_ASSOC_MASK, NR_ADDR_ASSOC); +} + +static void init_dev_cfg(struct devsec_dev *devsec_dev) +{ + void __iomem *base = devsec_base(devsec_dev), *cap_base; + int pos, next; + + /* BAR space */ + writew(0x8086, base + PCI_VENDOR_ID); + writew(0xffff, base + PCI_DEVICE_ID); + writel(lower_32_bits(devsec_dev->mmio_range.start) | + PCI_BASE_ADDRESS_MEM_TYPE_64 | + PCI_BASE_ADDRESS_MEM_PREFETCH, + base + PCI_BASE_ADDRESS_0); + writel(upper_32_bits(devsec_dev->mmio_range.start), + base + PCI_BASE_ADDRESS_1); + + /* Capability init */ + writeb(PCI_HEADER_TYPE_NORMAL, base + PCI_HEADER_TYPE); + writew(PCI_STATUS_CAP_LIST, base + PCI_STATUS); + pos = 0x40; + writew(pos, base + PCI_CAPABILITY_LIST); + + /* PCI-E Capability */ + cap_base = base + pos; + writeb(PCI_CAP_ID_EXP, cap_base); + writew(PCI_EXP_TYPE_ENDPOINT, cap_base + PCI_EXP_FLAGS); + writew(PCI_EXP_LNKSTA_CLS_2_5GB | PCI_EXP_LNKSTA_NLW_X1, cap_base + PCI_EXP_LNKSTA); + writel(PCI_EXP_DEVCAP_FLR | PCI_EXP_DEVCAP_TEE, cap_base + PCI_EXP_DEVCAP); + + /* DOE Extended Capability */ + pos = PCI_CFG_SPACE_SIZE; + next = pos + PCI_DOE_CAP_SIZEOF; + cap_base = base + pos; + devsec_dev->doe.cap = pos; + writel(build_ext_cap_header(PCI_EXT_CAP_ID_DOE, 2, next), cap_base); + + /* IDE Extended Capability */ + pos = next; + cap_base = base + pos; + writel(build_ext_cap_header(PCI_EXT_CAP_ID_IDE, 1, 0), cap_base); + devsec_dev->ide_pos = pos + 4; + init_ide(&devsec_dev->ide); +} + +#define MMIO_SIZE SZ_2M + +static int alloc_devs(struct devsec *devsec) +{ + struct device *dev = devsec->dev; + int i, rc; + + rc = devm_add_action_or_reset(dev, destroy_devs, devsec); + if (rc) + return rc; + + for (i = 0; i < ARRAY_SIZE(devsec->devsec_devs); i++) { + struct devsec_dev *devsec_dev __free(kfree) = + kzalloc(sizeof(*devsec_dev), GFP_KERNEL); + struct genpool_data_align data = { + .align = MMIO_SIZE, + }; + u64 phys; + + if (!devsec_dev) + return -ENOMEM; + + phys = gen_pool_alloc_algo(devsec->iomem_pool, MMIO_SIZE, + gen_pool_first_fit_align, &data); + if (!phys) + return -ENOMEM; + + devsec_dev->mmio_range = (struct range) { + .start = phys, + .end = phys + MMIO_SIZE - 1, + }; + init_dev_cfg(devsec_dev); + devsec->devsec_devs[i] = no_free_ptr(devsec_dev); + } + + return 0; +} + +static void destroy_ports(void *data) +{ + struct devsec *devsec = data; + int i; + + for (i = ARRAY_SIZE(devsec->devsec_ports) - 1; i >= 0; i--) { + struct devsec_port *devsec_port = devsec->devsec_ports[i]; + + if (!devsec_port) + continue; + pci_bridge_emul_cleanup(&devsec_port->bridge); + kfree(devsec_port); + devsec->devsec_ports[i] = NULL; + } +} + +static pci_bridge_emul_read_status_t +devsec_bridge_read_base(struct pci_bridge_emul *bridge, int pos, u32 *val) +{ + return PCI_BRIDGE_EMUL_NOT_HANDLED; +} + +static pci_bridge_emul_read_status_t +devsec_bridge_read_pcie(struct pci_bridge_emul *bridge, int pos, u32 *val) +{ + return PCI_BRIDGE_EMUL_NOT_HANDLED; +} + +static pci_bridge_emul_read_status_t +devsec_bridge_read_ext(struct pci_bridge_emul *bridge, int pos, u32 *val) +{ + struct devsec_port *devsec_port = bridge->data; + + /* only one extended capability, IDE... */ + if (pos == 0) { + *val = build_ext_cap_header(PCI_EXT_CAP_ID_IDE, 1, 0); + return PCI_BRIDGE_EMUL_HANDLED; + } + + if (pos < 4) + return PCI_BRIDGE_EMUL_NOT_HANDLED; + + pos -= 4; + if (pos < sizeof(struct devsec_ide)) { + *val = *(u32 *)(&devsec_port->ide_regs[pos]); + return PCI_BRIDGE_EMUL_HANDLED; + } + + return PCI_BRIDGE_EMUL_NOT_HANDLED; +} + +static void devsec_bridge_write_base(struct pci_bridge_emul *bridge, int pos, + u32 old, u32 new, u32 mask) +{ +} + +static void devsec_bridge_write_pcie(struct pci_bridge_emul *bridge, int pos, + u32 old, u32 new, u32 mask) +{ +} + +static void devsec_bridge_write_ext(struct pci_bridge_emul *bridge, int pos, + u32 old, u32 new, u32 mask) +{ + struct devsec_port *devsec_port = bridge->data; + + if (pos < sizeof(struct devsec_ide)) + *(u32 *)(&devsec_port->ide_regs[pos]) = new; +} + +static const struct pci_bridge_emul_ops devsec_bridge_ops = { + .read_base = devsec_bridge_read_base, + .write_base = devsec_bridge_write_base, + .read_pcie = devsec_bridge_read_pcie, + .write_pcie = devsec_bridge_write_pcie, + .read_ext = devsec_bridge_read_ext, + .write_ext = devsec_bridge_write_ext, +}; + +static int init_port(struct devsec_port *devsec_port) +{ + struct pci_bridge_emul *bridge = &devsec_port->bridge; + int rc; + + bridge->conf.vendor = cpu_to_le16(0x8086); + bridge->conf.device = cpu_to_le16(0x7075); + bridge->subsystem_vendor_id = cpu_to_le16(0x8086); + bridge->conf.class_revision = cpu_to_le32(0x1); + + bridge->conf.pref_mem_base = cpu_to_le16(PCI_PREF_RANGE_TYPE_64); + bridge->conf.pref_mem_limit = cpu_to_le16(PCI_PREF_RANGE_TYPE_64); + + bridge->has_pcie = true; + bridge->pcie_conf.devcap = cpu_to_le16(PCI_EXP_DEVCAP_FLR); + bridge->pcie_conf.lnksta = cpu_to_le16(PCI_EXP_LNKSTA_CLS_2_5GB); + + bridge->data = devsec_port; + bridge->ops = &devsec_bridge_ops; + + init_ide(&devsec_port->ide); + + rc = pci_bridge_emul_init(bridge, 0); + if (rc) + return rc; + + return 0; +} + +static int alloc_ports(struct devsec *devsec) +{ + struct device *dev = devsec->dev; + int i, rc; + + rc = devm_add_action_or_reset(dev, destroy_ports, devsec); + if (rc) + return rc; + + for (i = 0; i < ARRAY_SIZE(devsec->devsec_ports); i++) { + struct devsec_port *devsec_port __free(kfree) = + kzalloc(sizeof(*devsec_port), GFP_KERNEL); + + if (!devsec_port) + return -ENOMEM; + + rc = init_port(devsec_port); + if (rc) + return rc; + devsec->devsec_ports[i] = no_free_ptr(devsec_port); + } + + return 0; +} + +static int __init devsec_bus_probe(struct platform_device *pdev) +{ + int rc; + LIST_HEAD(resources); + struct devsec *devsec; + struct pci_sysdata *sd; + u64 mmio_size = SZ_64G; + struct device *dev = &pdev->dev; + u64 mmio_start = iomem_resource.end + 1 - SZ_64G; + + devsec = devm_kzalloc(dev, sizeof(*devsec), GFP_KERNEL); + if (!devsec) + return -ENOMEM; + + devsec->dev = dev; + devsec->iomem_pool = gen_pool_create(ilog2(SZ_2M), NUMA_NO_NODE); + if (!devsec->iomem_pool) + return -ENOMEM; + + rc = devm_add_action_or_reset(dev, destroy_iomem_pool, devsec); + if (rc) + return rc; + + rc = gen_pool_add(devsec->iomem_pool, mmio_start, mmio_size, + NUMA_NO_NODE); + if (rc) + return rc; + + devsec->resource[0] = (struct resource) { + .name = "DEVSEC BUSES", + .start = 0, + .end = NR_DEVSEC_BUSES + NR_DEVSEC_ROOT_PORTS - 1, + .flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED, + }; + pci_add_resource(&resources, &devsec->resource[0]); + + devsec->resource[1] = (struct resource) { + .name = "DEVSEC MMIO", + .start = mmio_start, + .end = mmio_start + mmio_size - 1, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_64, + }; + pci_add_resource(&resources, &devsec->resource[1]); + + sd = &devsec->sysdata; + devsec_sysdata = sd; + sd->domain = find_free_domain(); + if (sd->domain < 0) + return sd->domain; + + devsec->bus = pci_create_root_bus(dev, 0, &devsec_ops, + &devsec->sysdata, &resources); + if (!devsec->bus) { + pci_free_resource_list(&resources); + return -ENOMEM; + } + + rc = devm_add_action_or_reset(dev, destroy_bus, devsec); + if (rc) + return rc; + + rc = alloc_ports(devsec); + if (rc) + return rc; + + rc = alloc_devs(devsec); + if (rc) + return rc; + + pci_scan_child_bus(devsec->bus); + + return 0; +} + +static struct platform_driver devsec_bus_driver = { + .driver = { + .name = "devsec_bus", + }, +}; + +static struct platform_device *devsec_bus; + +static int __init devsec_bus_init(void) +{ + struct platform_device_info devsec_bus_info = { + .name = "devsec_bus", + .id = -1, + }; + int rc; + + devsec_bus = platform_device_register_full(&devsec_bus_info); + if (IS_ERR(devsec_bus)) + return PTR_ERR(devsec_bus); + + rc = platform_driver_probe(&devsec_bus_driver, devsec_bus_probe); + if (rc) + platform_device_unregister(devsec_bus); + return 0; +} +module_init(devsec_bus_init); + +static void __exit devsec_bus_exit(void) +{ + platform_driver_unregister(&devsec_bus_driver); + platform_device_unregister(devsec_bus); +} +module_exit(devsec_bus_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Device Security Sample Infrastructure: TDISP Device Emulation"); diff --git a/samples/devsec/common.c b/samples/devsec/common.c new file mode 100644 index 000000000000..9b6f4022f241 --- /dev/null +++ b/samples/devsec/common.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2024 Intel Corporation. All rights reserved. + +#include +#include + +/* + * devsec_bus and devsec_tsm need a common location for this data to + * avoid depending on each other. Enables load order testing + */ +struct pci_sysdata *devsec_sysdata; +EXPORT_SYMBOL_GPL(devsec_sysdata); + +static int __init common_init(void) +{ + return 0; +} +module_init(common_init); + +static void __exit common_exit(void) +{ +} +module_exit(common_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Device Security Sample Infrastructure: Shared data"); diff --git a/samples/devsec/devsec.h b/samples/devsec/devsec.h new file mode 100644 index 000000000000..794a9898ee2d --- /dev/null +++ b/samples/devsec/devsec.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +// Copyright(c) 2024 Intel Corporation. All rights reserved. + +#ifndef __DEVSEC_H__ +#define __DEVSEC_H__ +extern struct pci_sysdata *devsec_sysdata; +#endif /* __DEVSEC_H__ */ diff --git a/samples/devsec/tsm.c b/samples/devsec/tsm.c new file mode 100644 index 000000000000..d446ab8879d8 --- /dev/null +++ b/samples/devsec/tsm.c @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +// Copyright(c) 2024 Intel Corporation. All rights reserved. + +#define dev_fmt(fmt) "devsec: " fmt +#include +#include +#include +#include +#include +#include "devsec.h" + +struct devsec_dsm { + struct pci_dsm pci; +}; + +static struct devsec_dsm *to_devsec_dsm(struct pci_dsm *dsm) +{ + return container_of(dsm, struct devsec_dsm, pci); +} + +static struct pci_dsm *devsec_tsm_pci_probe(struct pci_dev *pdev) +{ + struct devsec_dsm *devsec_dsm; + + if (pdev->sysdata != devsec_sysdata) + return NULL; + + devsec_dsm = kzalloc(sizeof(*devsec_dsm), GFP_KERNEL); + if (!devsec_dsm) + return NULL; + + devsec_dsm->pci.pdev = pdev; + pci_dbg(pdev, "tsm enabled\n"); + return &devsec_dsm->pci; +} + +static void devsec_tsm_pci_remove(struct pci_dsm *dsm) +{ + struct devsec_dsm *devsec_dsm = to_devsec_dsm(dsm); + + pci_dbg(dsm->pdev, "tsm disabled\n"); + kfree(devsec_dsm); +} + +static int devsec_tsm_connect(struct pci_dev *pdev) +{ + return -ENXIO; +} + +static void devsec_tsm_disconnect(struct pci_dev *pdev) +{ +} + +static const struct pci_tsm_ops devsec_pci_ops = { + .probe = devsec_tsm_pci_probe, + .remove = devsec_tsm_pci_remove, + .connect = devsec_tsm_connect, + .disconnect = devsec_tsm_disconnect, +}; + +static void devsec_tsm_remove(void *tsm) +{ + tsm_unregister(tsm); +} + +static int devsec_tsm_probe(struct platform_device *pdev) +{ + struct tsm_subsys *tsm; + + tsm = tsm_register(&pdev->dev, NULL, &devsec_pci_ops); + if (IS_ERR(tsm)) + return PTR_ERR(tsm); + + return devm_add_action_or_reset(&pdev->dev, devsec_tsm_remove, + tsm); +} + +static struct platform_driver devsec_tsm_driver = { + .driver = { + .name = "devsec_tsm", + }, +}; + +static struct platform_device *devsec_tsm; + +static int __init devsec_tsm_init(void) +{ + struct platform_device_info devsec_tsm_info = { + .name = "devsec_tsm", + .id = -1, + }; + int rc; + + devsec_tsm = platform_device_register_full(&devsec_tsm_info); + if (IS_ERR(devsec_tsm)) + return PTR_ERR(devsec_tsm); + + rc = platform_driver_probe(&devsec_tsm_driver, devsec_tsm_probe); + if (rc) + platform_device_unregister(devsec_tsm); + return rc; +} +module_init(devsec_tsm_init); + +static void __exit devsec_tsm_exit(void) +{ + platform_driver_unregister(&devsec_tsm_driver); + platform_device_unregister(devsec_tsm); +} +module_exit(devsec_tsm_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Device Security Sample Infrastructure: Platform TSM Driver"); From patchwork Thu Dec 5 22:23:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 13896054 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) (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 0AA521CCEF8 for ; Thu, 5 Dec 2024 22:23:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437439; cv=none; b=gD6Id4czZAnsW32aLk1ZWObNqy2NLXTzpDcHk4fPOlK9mCR1/Zv2uIXw2UfHU7OQP3218p+bDUKoGP4dpyY+oAxHSaNTft4Nb0S3m3MlyT9XjIJlh/5cdoWSpyYyiN5vZhVjqoPulZL8e4ISlGXwLUdOaby9BIWi06JK4qDqI4o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437439; c=relaxed/simple; bh=xFHmZBWJPr9bAxkc/LrrW+59qUpbdh11WV1EQ2Bc3Fk=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=eJsh4W6JtV3a9yGxBpOl+6csbJHrRyS1zDp/uhUKs+zMhG+dN48nvR5iYzwa7jZDZL5rU4XFniwIdN/xpsWS64S7dVW56ygl46w1hqNP7z5YUPBRM5SjmWPVAnap52CXHleJHHA+GmtfVDRAUESLKdEkwV5Xnen5dPzWzJcWSLs= ARC-Authentication-Results: i=1; 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=WJNdnujj; arc=none smtp.client-ip=198.175.65.16 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="WJNdnujj" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733437438; x=1764973438; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xFHmZBWJPr9bAxkc/LrrW+59qUpbdh11WV1EQ2Bc3Fk=; b=WJNdnujjYEh+spP03oxEtyS1wUv2t2y/vIkNVSjvVyGCHRb22y+MG6Ec Yc3VbN+hj+zKKVhq28O7EfFh73RqkqgNzwlyQtmvVi0aDAwuTGid9BZ0W 8I1C4N00Hyu2/s2NApRavl0Q7vx0fa5KKFAY+/EZOHkJMNiB/b5wAZ0Et 8Kg/eV2WZxXdxJAHJ8KpR2sLEDYDtU+Youv3QXxeSYsfujK87VgBNBsLj cNPlDv1hOB4K84rUI3tWeN86Y1dSKycd+iMDw5nuBuikIgfLopcriBjUj lOirwON7KGmVzL65Keg+BFkhnYtTbl2nmUGyvS+pFQB88gvlKSLzCFMPk g==; X-CSE-ConnectionGUID: YFcR/JYDRWeEfsSf6WFZIg== X-CSE-MsgGUID: 1/NHhkspS2er5+z/UFOCww== X-IronPort-AV: E=McAfee;i="6700,10204,11277"; a="33910450" X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="33910450" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:58 -0800 X-CSE-ConnectionGUID: r08nk+EVT3qcv7ocWN7RHg== X-CSE-MsgGUID: Qgq3q9+KTAWmP7bPEXacyg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="99050142" Received: from kcaccard-desk.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.125.108.178]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:23:57 -0800 Subject: [PATCH 07/11] PCI: Add PCIe Device 3 Extended Capability enumeration From: Dan Williams To: linux-coco@lists.linux.dev Cc: Lukas Wunner , Ilpo =?utf-8?b?SsOkcnZpbmVu?= , Bjorn Helgaas , Samuel Ortiz , Alexey Kardashevskiy , Xu Yilun , linux-pci@vger.kernel.org, gregkh@linuxfoundation.org Date: Thu, 05 Dec 2024 14:23:56 -0800 Message-ID: <173343743678.1074769.15403889527436764173.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> References: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 PCIe 6.2 Section 7.7.9 Device 3 Extended Capability Structure, enumerates new link capabilities and status added for Gen 6 devices. One of the link details enumerated in that register block is the "Segment Captured" status in the Device Status 3 register. That status is relevant for enabling IDE (Integrity & Data Encryption) whereby Selective IDE streams can be limited to a given requester id range within a given segment. If a device has captured its Segment value then it knows that PCIe Flit Mode is enabled via all links in the path that a configuration write traversed. IDE establishment requires that "Segment Base" in IDE RID Association Register 2 (PCIe 6.2 Section 7.9.26.5.4.2) be programmed if the RID association mechanism is in effect. When / if IDE + Flit Mode capable devices arrive, the PCI core needs to setup the segment base when using the RID association facility, but no known deployments today depend on this. Cc: Lukas Wunner Cc: Ilpo Järvinen Cc: Bjorn Helgaas Cc: Samuel Ortiz Cc: Alexey Kardashevskiy Cc: Xu Yilun Signed-off-by: Dan Williams --- drivers/pci/pci.h | 11 +++++++++++ drivers/pci/probe.c | 1 + include/linux/pci.h | 1 + include/uapi/linux/pci_regs.h | 7 +++++++ 4 files changed, 20 insertions(+) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 0537fc72d5be..6565eb72ded2 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -444,6 +444,17 @@ static inline void pci_doe_destroy(struct pci_dev *pdev) { } static inline void pci_doe_disconnected(struct pci_dev *pdev) { } #endif +static inline void pci_dev3_init(struct pci_dev *pdev) +{ + u16 cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DEV3); + u32 val = 0; + + if (!cap) + return; + pci_read_config_dword(pdev, cap + PCI_DEV3_STA, &val); + pdev->fm_enabled = !!(val & PCI_DEV3_STA_SEGMENT); +} + #ifdef CONFIG_PCI_NPEM void pci_npem_create(struct pci_dev *dev); void pci_npem_remove(struct pci_dev *dev); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 7cddde3cb0ed..6c1fe6354d26 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2517,6 +2517,7 @@ static void pci_init_capabilities(struct pci_dev *dev) pci_rcec_init(dev); /* Root Complex Event Collector */ pci_doe_init(dev); /* Data Object Exchange */ pci_tph_init(dev); /* TLP Processing Hints */ + pci_dev3_init(dev); /* Device 3 capabilities */ pci_ide_init(dev); /* Link Integrity and Data Encryption */ pci_tsm_init(dev); /* TEE Security Manager connection */ diff --git a/include/linux/pci.h b/include/linux/pci.h index a0900e7d2012..10d035395a43 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -443,6 +443,7 @@ struct pci_dev { unsigned int pasid_enabled:1; /* Process Address Space ID */ unsigned int pri_enabled:1; /* Page Request Interface */ unsigned int tph_enabled:1; /* TLP Processing Hints */ + unsigned int fm_enabled:1; /* Flit Mode (segment captured) */ unsigned int is_managed:1; /* Managed via devres */ unsigned int is_msi_managed:1; /* MSI release via devres installed */ unsigned int needs_freset:1; /* Requires fundamental reset */ diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 19bba65a262c..c61231861b51 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -749,6 +749,7 @@ #define PCI_EXT_CAP_ID_NPEM 0x29 /* Native PCIe Enclosure Management */ #define PCI_EXT_CAP_ID_PL_32GT 0x2A /* Physical Layer 32.0 GT/s */ #define PCI_EXT_CAP_ID_DOE 0x2E /* Data Object Exchange */ +#define PCI_EXT_CAP_ID_DEV3 0x2F /* Device 3 Capability/Control/Status */ #define PCI_EXT_CAP_ID_IDE 0x30 /* Integrity and Data Encryption */ #define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_IDE @@ -1210,6 +1211,12 @@ #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL 0x00ff0000 #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX 0xff000000 +/* Device 3 Extended Capability */ +#define PCI_DEV3_CAP 0x4 /* Device 3 Capabilities Register */ +#define PCI_DEV3_CTL 0x8 /* Device 3 Control Register */ +#define PCI_DEV3_STA 0xc /* Device 3 Status Register */ +#define PCI_DEV3_STA_SEGMENT 0x8 /* Segment Captured (end-to-end flit-mode detected) */ + /* Compute Express Link (CXL r3.1, sec 8.1.5) */ #define PCI_DVSEC_CXL_PORT 3 #define PCI_DVSEC_CXL_PORT_CTL 0x0c From patchwork Thu Dec 5 22:24:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 13896055 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) (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 298F91C878E for ; Thu, 5 Dec 2024 22:24:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437446; cv=none; b=OVCsbc9sqDu90UzTzxW3iVmmdSAhqyCUYNdDANaGaYxIhtmFWRrkp4EWyCTY0qXQqYZjaRkMi3dFsbKBMFlt5c1DX/N+Myg5YSQwD09Et9YnaTpdrFY7uBNNEBtEYlmd8b1VdDAUFV+H0YSHKoUmXncXE7znb+WA4z3WOu94Pv0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437446; c=relaxed/simple; bh=Ctr3y6WelSUKaqCbghukVrA6vcI0M1eDXAmBvq79rXI=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=krNOMNdBjpfBwc6BpG2slIyuMv/PuARq8f/ubaaqERg/9oaVP7x+qEVe00WBYRrqJSFM6UkilA5KSwybQzAZ6+U2j3ZOdM0/j8LKyhZzk3Ib53Br0y5Kzwz0VVMlRJ+nEGZDgIJreJyH2QuqUkCFtw47DEsDBIwvr4QIE1O4nfw= ARC-Authentication-Results: i=1; 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=a9X6R9qI; arc=none smtp.client-ip=198.175.65.16 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="a9X6R9qI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733437444; x=1764973444; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Ctr3y6WelSUKaqCbghukVrA6vcI0M1eDXAmBvq79rXI=; b=a9X6R9qI45yjtfd+RmKWWwnHVBle66FkpEkcNUGhXAWIJ5jbjBh4g1Si 9jPBEcQwrIaz9AGOXbjAmtnthSp5iT20cFu9imUyb3e+gT6l7kGugPm7j MFgBwxjPTPWfrm6i0RDWwsvKp2h7FmTF1v8K/722uaUO2VMDH3eMH7qfx EZ7Hauet9lg93WTYuvfSZj/CoAep01X0CwRZpADl8pcskl/HBdvFAz5We jZUg/hZ0jOI5+DzkHU8OrlNOErKWtAAbQtCem960luEnRDtvHsUBQnJG7 atKMdGpUATLlxC1Km1n5mAOLxFVnAUVl01moRxvoRobFFm1XzLqvmqYJ9 w==; X-CSE-ConnectionGUID: b7QmWeFASMiiohi+y/dAtg== X-CSE-MsgGUID: 1OKt9urlRKOrWrTJqfcSZQ== X-IronPort-AV: E=McAfee;i="6700,10204,11277"; a="33910458" X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="33910458" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:24:04 -0800 X-CSE-ConnectionGUID: Z3GBsMxVSlWKu9pCivJc0A== X-CSE-MsgGUID: fB3wgmR7RquEJzGiDHVTDA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="99050170" Received: from kcaccard-desk.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.125.108.178]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:24:03 -0800 Subject: [PATCH 08/11] PCI/IDE: Add IDE establishment helpers From: Dan Williams To: linux-coco@lists.linux.dev Cc: Bjorn Helgaas , Lukas Wunner , Samuel Ortiz , Alexey Kardashevskiy , Xu Yilun , linux-pci@vger.kernel.org, gregkh@linuxfoundation.org Date: Thu, 05 Dec 2024 14:24:02 -0800 Message-ID: <173343744264.1074769.10935494914881159519.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> References: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 There are two components to establishing an encrypted link, provisioning the stream in config-space, and programming the keys into the link layer via the IDE_KM (key management) protocol. These helpers enable the former, and are in support of TSM coordinated IDE_KM. When / if native IDE establishment arrives it will share this same config-space provisioning flow, but for now IDE_KM, in any form, is saved for a follow-on change. With the TSM implementations of SEV-TIO and TDX Connect in mind this abstracts small differences in those implementations. For example, TDX Connect handles Root Port registers updates while SEV-TIO expects System Software to update the Root Port registers. This is the rationale for the PCI_IDE_SETUP_ROOT_PORT flag. The other design detail for TSM-coordinated IDE establishment is that the TSM manages allocation of stream-ids, this is why the stream_id is passed in to pci_ide_stream_setup(). The flow is: pci_ide_stream_probe() Gather stream settings (devid and address filters) pci_ide_stream_setup() Program the stream settings into the endpoint, and optionally Root Port) pci_ide_enable_stream() Run the stream after IDE_KM In support of system administrators auditing where platform IDE stream resources are being spent, the allocated stream is reflected as a symlink from the host-bridge to the endpoint. Thanks to Wu Hao for a draft implementation of this infrastructure. Cc: Bjorn Helgaas Cc: Lukas Wunner Cc: Samuel Ortiz Co-developed-by: Alexey Kardashevskiy Signed-off-by: Alexey Kardashevskiy Co-developed-by: Xu Yilun Signed-off-by: Xu Yilun Signed-off-by: Dan Williams --- .../ABI/testing/sysfs-devices-pci-host-bridge | 28 +++ drivers/pci/ide.c | 192 ++++++++++++++++++++ drivers/pci/pci.h | 4 drivers/pci/probe.c | 1 include/linux/pci-ide.h | 33 +++ include/linux/pci.h | 4 6 files changed, 262 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-devices-pci-host-bridge create mode 100644 include/linux/pci-ide.h diff --git a/Documentation/ABI/testing/sysfs-devices-pci-host-bridge b/Documentation/ABI/testing/sysfs-devices-pci-host-bridge new file mode 100644 index 000000000000..15dafb46b176 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-pci-host-bridge @@ -0,0 +1,28 @@ +What: /sys/devices/pciDDDDD:BB + /sys/devices/.../pciDDDDD:BB +Date: December, 2024 +Contact: linux-pci@vger.kernel.org +Description: + A PCI host bridge device parents a PCI bus device topology. PCI + controllers may also parent host bridges. The DDDDD:BB format + convey the PCI domain number and the bus number for root ports + of the host bridge. + +What: pciDDDDD:BB/firmware_node +Date: December, 2024 +Contact: linux-pci@vger.kernel.org +Description: + (RO) Symlink to the platform firmware device object "companion" + of the host bridge. For example, an ACPI device with an _HID of + PNP0A08 (/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00). + +What: pciDDDDD:BB/streamN:DDDDD:BB:DD:F +Date: December, 2024 +Contact: linux-pci@vger.kernel.org +Description: + (RO) When a host-bridge has established a secure connection, + typically PCIe IDE, between a host-bridge an endpoint, this + symlink appears. The primary function is to account how many + streams can be returned to the available secure streams pool by + invoking the tsm/disconnect flow. The link points to the + endpoint PCI device at domain:DDDDD bus:BB device:DD function:F. diff --git a/drivers/pci/ide.c b/drivers/pci/ide.c index a0c09d9e0b75..c37f35f0d2c0 100644 --- a/drivers/pci/ide.c +++ b/drivers/pci/ide.c @@ -5,6 +5,9 @@ #define dev_fmt(fmt) "PCI/IDE: " fmt #include +#include +#include +#include #include "pci.h" static int sel_ide_offset(u16 cap, int stream_id, int nr_ide_mem) @@ -71,3 +74,192 @@ void pci_ide_init(struct pci_dev *pdev) pdev->sel_ide_cap = sel_ide_cap; pdev->nr_ide_mem = nr_ide_mem; } + +void pci_init_host_bridge_ide(struct pci_host_bridge *hb) +{ + hb->ide_stream_res = + DEFINE_RES_MEM_NAMED(0, 0, "IDE Address Association"); +} + +/* + * Retrieve stream association parameters for devid (RID) and resources + * (device address ranges) + */ +void pci_ide_stream_probe(struct pci_dev *pdev, struct pci_ide *ide) +{ + int num_vf = pci_num_vf(pdev); + + *ide = (struct pci_ide) { .stream_id = -1 }; + + if (pdev->fm_enabled) + ide->domain = pci_domain_nr(pdev->bus); + ide->devid_start = pci_dev_id(pdev); + + /* for SR-IOV case, cover all VFs */ + if (num_vf) + ide->devid_end = PCI_DEVID(pci_iov_virtfn_bus(pdev, num_vf), + pci_iov_virtfn_devfn(pdev, num_vf)); + else + ide->devid_end = ide->devid_start; + + /* TODO: address association probing... */ +} +EXPORT_SYMBOL_GPL(pci_ide_stream_probe); + +static void __pci_ide_stream_teardown(struct pci_dev *pdev, struct pci_ide *ide) +{ + int pos; + + pos = sel_ide_offset(pdev->sel_ide_cap, ide->stream_id, + pdev->nr_ide_mem); + + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, 0); + for (int i = ide->nr_mem - 1; i >= 0; i--) { + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_3(i), 0); + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_2(i), 0); + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_1(i), 0); + } + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_2, 0); + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_1, 0); +} + +static void __pci_ide_stream_setup(struct pci_dev *pdev, struct pci_ide *ide) +{ + int pos; + u32 val; + + pos = sel_ide_offset(pdev->sel_ide_cap, ide->stream_id, + pdev->nr_ide_mem); + + val = FIELD_PREP(PCI_IDE_SEL_RID_1_LIMIT_MASK, ide->devid_end); + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_1, val); + + val = FIELD_PREP(PCI_IDE_SEL_RID_2_VALID, 1) | + FIELD_PREP(PCI_IDE_SEL_RID_2_BASE_MASK, ide->devid_start) | + FIELD_PREP(PCI_IDE_SEL_RID_2_SEG_MASK, ide->domain); + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_2, val); + + for (int i = 0; i < ide->nr_mem; i++) { + val = FIELD_PREP(PCI_IDE_SEL_ADDR_1_VALID, 1) | + FIELD_PREP(PCI_IDE_SEL_ADDR_1_BASE_LOW_MASK, + lower_32_bits(ide->mem[i].start) >> + PCI_IDE_SEL_ADDR_1_BASE_LOW_SHIFT) | + FIELD_PREP(PCI_IDE_SEL_ADDR_1_LIMIT_LOW_MASK, + lower_32_bits(ide->mem[i].end) >> + PCI_IDE_SEL_ADDR_1_LIMIT_LOW_SHIFT); + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_1(i), val); + + val = upper_32_bits(ide->mem[i].end); + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_2(i), val); + + val = upper_32_bits(ide->mem[i].start); + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_3(i), val); + } +} + +/* + * Establish IDE stream parameters in @pdev and, optionally, its root port + */ +int pci_ide_stream_setup(struct pci_dev *pdev, struct pci_ide *ide, + enum pci_ide_flags flags) +{ + struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus); + struct pci_dev *rp = pcie_find_root_port(pdev); + int mem = 0, rc; + + if (ide->stream_id < 0 || ide->stream_id > U8_MAX) { + pci_err(pdev, "Setup fail: Invalid stream id: %d\n", ide->stream_id); + return -ENXIO; + } + + if (test_and_set_bit_lock(ide->stream_id, hb->ide_stream_ids)) { + pci_err(pdev, "Setup fail: Busy stream id: %d\n", + ide->stream_id); + return -EBUSY; + } + + ide->name = kasprintf(GFP_KERNEL, "stream%d:%s", ide->stream_id, + dev_name(&pdev->dev)); + if (!ide->name) { + rc = -ENOMEM; + goto err_name; + } + + rc = sysfs_create_link(&hb->dev.kobj, &pdev->dev.kobj, ide->name); + if (rc) + goto err_link; + + for (mem = 0; mem < ide->nr_mem; mem++) + if (!__request_region(&hb->ide_stream_res, ide->mem[mem].start, + range_len(&ide->mem[mem]), ide->name, + 0)) { + pci_err(pdev, + "Setup fail: stream%d: address association conflict [%#llx-%#llx]\n", + ide->stream_id, ide->mem[mem].start, + ide->mem[mem].end); + + rc = -EBUSY; + goto err; + } + + __pci_ide_stream_setup(pdev, ide); + if (flags & PCI_IDE_SETUP_ROOT_PORT) + __pci_ide_stream_setup(rp, ide); + + return 0; +err: + for (; mem >= 0; mem--) + __release_region(&hb->ide_stream_res, ide->mem[mem].start, + range_len(&ide->mem[mem])); + sysfs_remove_link(&hb->dev.kobj, ide->name); +err_link: + kfree(ide->name); +err_name: + clear_bit_unlock(ide->stream_id, hb->ide_stream_ids); + return rc; +} +EXPORT_SYMBOL_GPL(pci_ide_stream_setup); + +void pci_ide_enable_stream(struct pci_dev *pdev, struct pci_ide *ide) +{ + int pos; + u32 val; + + pos = sel_ide_offset(pdev->sel_ide_cap, ide->stream_id, + pdev->nr_ide_mem); + + val = FIELD_PREP(PCI_IDE_SEL_CTL_ID_MASK, ide->stream_id) | + FIELD_PREP(PCI_IDE_SEL_CTL_DEFAULT, 1); + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, val); +} +EXPORT_SYMBOL_GPL(pci_ide_enable_stream); + +void pci_ide_disable_stream(struct pci_dev *pdev, struct pci_ide *ide) +{ + int pos; + + pos = sel_ide_offset(pdev->sel_ide_cap, ide->stream_id, + pdev->nr_ide_mem); + + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, 0); +} +EXPORT_SYMBOL_GPL(pci_ide_disable_stream); + +void pci_ide_stream_teardown(struct pci_dev *pdev, struct pci_ide *ide, + enum pci_ide_flags flags) +{ + struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus); + struct pci_dev *rp = pcie_find_root_port(pdev); + + __pci_ide_stream_teardown(pdev, ide); + if (flags & PCI_IDE_SETUP_ROOT_PORT) + __pci_ide_stream_teardown(rp, ide); + + for (int i = ide->nr_mem - 1; i >= 0; i--) + __release_region(&hb->ide_stream_res, ide->mem[i].start, + range_len(&ide->mem[i])); + sysfs_remove_link(&hb->dev.kobj, ide->name); + kfree(ide->name); + clear_bit_unlock(ide->stream_id, hb->ide_stream_ids); +} +EXPORT_SYMBOL_GPL(pci_ide_stream_teardown); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 6565eb72ded2..b267fabfd542 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -465,8 +465,12 @@ static inline void pci_npem_remove(struct pci_dev *dev) { } #ifdef CONFIG_PCI_IDE void pci_ide_init(struct pci_dev *dev); +void pci_init_host_bridge_ide(struct pci_host_bridge *bridge); #else static inline void pci_ide_init(struct pci_dev *dev) { } +static inline void pci_init_host_bridge_ide(struct pci_host_bridge *bridge) +{ +} #endif #ifdef CONFIG_PCI_TSM diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6c1fe6354d26..667faa18ced2 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -608,6 +608,7 @@ static void pci_init_host_bridge(struct pci_host_bridge *bridge) bridge->native_dpc = 1; bridge->domain_nr = PCI_DOMAIN_NR_NOT_SET; bridge->native_cxl_error = 1; + pci_init_host_bridge_ide(bridge); device_initialize(&bridge->dev); } diff --git a/include/linux/pci-ide.h b/include/linux/pci-ide.h new file mode 100644 index 000000000000..24e08a413645 --- /dev/null +++ b/include/linux/pci-ide.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2024 Intel Corporation. All rights reserved. */ + +/* PCIe 6.2 section 6.33 Integrity & Data Encryption (IDE) */ + +#ifndef __PCI_IDE_H__ +#define __PCI_IDE_H__ + +#include + +struct pci_ide { + int domain; + u16 devid_start; + u16 devid_end; + int stream_id; + const char *name; + int nr_mem; + struct range mem[16]; +}; + +void pci_ide_stream_probe(struct pci_dev *pdev, struct pci_ide *ide); + +enum pci_ide_flags { + PCI_IDE_SETUP_ROOT_PORT = BIT(0), +}; + +int pci_ide_stream_setup(struct pci_dev *pdev, struct pci_ide *ide, + enum pci_ide_flags flags); +void pci_ide_stream_teardown(struct pci_dev *pdev, struct pci_ide *ide, + enum pci_ide_flags flags); +void pci_ide_enable_stream(struct pci_dev *pdev, struct pci_ide *ide); +void pci_ide_disable_stream(struct pci_dev *pdev, struct pci_ide *ide); +#endif /* __PCI_IDE_H__ */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 10d035395a43..5d9fc498bc70 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -601,6 +601,10 @@ struct pci_host_bridge { int domain_nr; struct list_head windows; /* resource_entry */ struct list_head dma_ranges; /* dma ranges resource list */ +#ifdef CONFIG_PCI_IDE /* track IDE stream id allocation */ + DECLARE_BITMAP(ide_stream_ids, PCI_IDE_SEL_CTL_ID_MAX + 1); + struct resource ide_stream_res; /* track ide stream address association */ +#endif u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* Platform IRQ swizzler */ int (*map_irq)(const struct pci_dev *, u8, u8); void (*release_fn)(struct pci_host_bridge *); From patchwork Thu Dec 5 22:24:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 13896056 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.13]) (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 B312E1BD51B for ; Thu, 5 Dec 2024 22:24:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437451; cv=none; b=NeyjecKux006XKh9UbytcpofwHH9js4keEjw/s7EKuiB59sY9/BrvahjmaGjkG3Nr4iye8xFV7liaxEZ3ZUcqE4v7kLONUYQK095RSwcOx5GnGAWTQgv64GynGY+sKGnVCIYvM8ZGcmDbxkA2KOWu3INgsAeO0OvV32O/0Ye4RY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437451; c=relaxed/simple; bh=+k2d4np08krIYuCxOkZ6CLhFSEDzFgxDvVHfbkVQxM0=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=gMniPYkW1qMWOkrmijsipBnvnzw00H1F8wOR9GNwnhaoLyrUODX6jGT1ylF0LrPnESCvR+hppPb7cZqohHjk3k1WV591WpPgtIQg02ItN/Wmzdnix960wVkFzuBUMs4Up/UWmbKXzZdGOwLqmxS9dyryJs6YSRoWCUOpokPpJKc= ARC-Authentication-Results: i=1; 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=C+7kMcVS; arc=none smtp.client-ip=198.175.65.13 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="C+7kMcVS" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733437450; x=1764973450; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+k2d4np08krIYuCxOkZ6CLhFSEDzFgxDvVHfbkVQxM0=; b=C+7kMcVS66idWI+OLxambHIqE5KvpWjSZxPJpX7r5hUZZ1bXbTGgnfEt 0C9KCrumwbKkVAU3K92EGA+XzRWwgJPb7LyjzCA8SFnLT4rjhiydtn571 OAIHDHIf1RE7p1ckPqvXKGIUwSPRSdf3gLiqBDlne6yJjRgj6+u8vJdgk AwxpS5RZ3BaPxbQiSybuuLn8I78xJkL6GJFNIOr843G7hNS+l20W/b6Xw qgjvw25Jj0zV/t07UWri9aeZ6lizWeQE81L431dpFJ/GpZkp5gmGQPGeQ 6+xOoB/TzsItQrkaTjuERMxdVOhLFvkZ4a+aoh4bkfiB/Km1aGmExDKAK w==; X-CSE-ConnectionGUID: AZIxBQ60T1yg5BOuXCnefg== X-CSE-MsgGUID: xJEW+3AiRdyMHUVy7NztcA== X-IronPort-AV: E=McAfee;i="6700,10204,11277"; a="44802861" X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="44802861" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:24:09 -0800 X-CSE-ConnectionGUID: gWJd4ZfXQZqK7NOQbyptaw== X-CSE-MsgGUID: Jivy9iZaSfKJttcDIFw1KA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="99301844" Received: from kcaccard-desk.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.125.108.178]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:24:10 -0800 Subject: [PATCH 09/11] PCI/IDE: Report available IDE streams From: Dan Williams To: linux-coco@lists.linux.dev Cc: Bjorn Helgaas , Lukas Wunner , Samuel Ortiz , Alexey Kardashevskiy , Xu Yilun , linux-pci@vger.kernel.org, gregkh@linuxfoundation.org Date: Thu, 05 Dec 2024 14:24:08 -0800 Message-ID: <173343744869.1074769.12345445223792172558.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> References: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The limited number of link-encryption (IDE) streams that a given set of host-bridges supports is a platform specific detail. Provide pci_set_nr_ide_streams() as a generic facility for either platform TSM drivers, or in the future PCI core native IDE, to report the number available streams. After invoking pci_set_nr_ide_streams() an "available_secure_streams" attribute appears in PCI Host Bridge sysfs to convey how many streams are available for IDE establishment. Cc: Bjorn Helgaas Cc: Lukas Wunner Cc: Samuel Ortiz Cc: Alexey Kardashevskiy Cc: Xu Yilun Signed-off-by: Dan Williams --- .../ABI/testing/sysfs-devices-pci-host-bridge | 11 +++++ drivers/pci/ide.c | 46 ++++++++++++++++++++ drivers/pci/pci.h | 3 + drivers/pci/probe.c | 11 ++++- include/linux/pci.h | 9 ++++ 5 files changed, 79 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-devices-pci-host-bridge b/Documentation/ABI/testing/sysfs-devices-pci-host-bridge index 15dafb46b176..1a3249f20e48 100644 --- a/Documentation/ABI/testing/sysfs-devices-pci-host-bridge +++ b/Documentation/ABI/testing/sysfs-devices-pci-host-bridge @@ -26,3 +26,14 @@ Description: streams can be returned to the available secure streams pool by invoking the tsm/disconnect flow. The link points to the endpoint PCI device at domain:DDDDD bus:BB device:DD function:F. + +What: pciDDDDD:BB/available_secure_streams +Date: December, 2024 +Contact: linux-pci@vger.kernel.org +Description: + (RO) When a host-bridge has root ports that support PCIe IDE + (link encryption and integrity protection) there may be a + limited number of streams that can be used for establishing new + secure links. This attribute decrements upon secure link setup, + and increments upon secure link teardown. The in-use stream + count is determined by counting stream symlinks. diff --git a/drivers/pci/ide.c b/drivers/pci/ide.c index c37f35f0d2c0..0abc19b341ab 100644 --- a/drivers/pci/ide.c +++ b/drivers/pci/ide.c @@ -75,8 +75,54 @@ void pci_ide_init(struct pci_dev *pdev) pdev->nr_ide_mem = nr_ide_mem; } +static ssize_t available_secure_streams_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct pci_host_bridge *hb = to_pci_host_bridge(dev); + int avail; + + if (hb->nr_ide_streams < 0) + return -ENXIO; + + avail = hb->nr_ide_streams - + bitmap_weight(hb->ide_stream_ids, PCI_IDE_SEL_CTL_ID_MAX + 1); + return sysfs_emit(buf, "%d\n", avail); +} +static DEVICE_ATTR_RO(available_secure_streams); + +static struct attribute *pci_ide_attrs[] = { + &dev_attr_available_secure_streams.attr, + NULL, +}; + +static umode_t pci_ide_attr_visible(struct kobject *kobj, struct attribute *a, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct pci_host_bridge *hb = to_pci_host_bridge(dev); + + if (a == &dev_attr_available_secure_streams.attr) + if (hb->nr_ide_streams < 0) + return 0; + + return a->mode; +} + +struct attribute_group pci_ide_attr_group = { + .attrs = pci_ide_attrs, + .is_visible = pci_ide_attr_visible, +}; + +void pci_set_nr_ide_streams(struct pci_host_bridge *hb, int nr) +{ + hb->nr_ide_streams = nr; + sysfs_update_group(&hb->dev.kobj, &pci_ide_attr_group); +} +EXPORT_SYMBOL_NS_GPL(pci_set_nr_ide_streams, PCI_IDE); + void pci_init_host_bridge_ide(struct pci_host_bridge *hb) { + hb->nr_ide_streams = -1; hb->ide_stream_res = DEFINE_RES_MEM_NAMED(0, 0, "IDE Address Association"); } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index b267fabfd542..76f18b07e081 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -466,11 +466,14 @@ static inline void pci_npem_remove(struct pci_dev *dev) { } #ifdef CONFIG_PCI_IDE void pci_ide_init(struct pci_dev *dev); void pci_init_host_bridge_ide(struct pci_host_bridge *bridge); +extern struct attribute_group pci_ide_attr_group; +#define PCI_IDE_ATTR_GROUP (&pci_ide_attr_group) #else static inline void pci_ide_init(struct pci_dev *dev) { } static inline void pci_init_host_bridge_ide(struct pci_host_bridge *bridge) { } +#define PCI_IDE_ATTR_GROUP NULL #endif #ifdef CONFIG_PCI_TSM diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 667faa18ced2..a85ad3b28028 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -589,6 +589,16 @@ static void pci_release_host_bridge_dev(struct device *dev) kfree(bridge); } +static const struct attribute_group *pci_host_bridge_groups[] = { + PCI_IDE_ATTR_GROUP, + NULL, +}; + +static const struct device_type pci_host_bridge_type = { + .groups = pci_host_bridge_groups, + .release = pci_release_host_bridge_dev, +}; + static void pci_init_host_bridge(struct pci_host_bridge *bridge) { INIT_LIST_HEAD(&bridge->windows); @@ -622,7 +632,6 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv) return NULL; pci_init_host_bridge(bridge); - bridge->dev.release = pci_release_host_bridge_dev; return bridge; } diff --git a/include/linux/pci.h b/include/linux/pci.h index 5d9fc498bc70..eae3d11710db 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -604,6 +604,7 @@ struct pci_host_bridge { #ifdef CONFIG_PCI_IDE /* track IDE stream id allocation */ DECLARE_BITMAP(ide_stream_ids, PCI_IDE_SEL_CTL_ID_MAX + 1); struct resource ide_stream_res; /* track ide stream address association */ + int nr_ide_streams; #endif u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* Platform IRQ swizzler */ int (*map_irq)(const struct pci_dev *, u8, u8); @@ -654,6 +655,14 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge, void (*release_fn)(struct pci_host_bridge *), void *release_data); +#ifdef CONFIG_PCI_IDE +void pci_set_nr_ide_streams(struct pci_host_bridge *hb, int nr); +#else +static inline void pci_set_nr_ide_streams(struct pci_host_bridge *hb, int nr) +{ +} +#endif + int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge); #define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */ From patchwork Thu Dec 5 22:24:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 13896057 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.13]) (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 A93521BD51B for ; Thu, 5 Dec 2024 22:24:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437457; cv=none; b=FRd4ENlXAh8cQ8gVcOzgyjrUIzzlpecNLpk54ds7kzgRYYWYlT2yjyaWAamsQLDR7SKt/WcEccuiaWkd36kJClKXwsRadNoZF384RgzSFAmvtrUHr+wL1Lk50K0tXi0JWlB4AiOTA0A13SAV8txwzLZbPjxwMbYE3/a4nk8/34Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437457; c=relaxed/simple; bh=MSQyo461+ACp9WGYclqMonspDGXAxbE8gwEgXJXAzT0=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=cfUH1aoazTr7v121SKjyWaAZ2LXKe0GkUqnqyHZ8R3QPE3mA1fjEme+gK2bv8KEB/xkUM6AYMPApWRTnRXnXM+s6p7Ia8fLy1QXQPVtLky5jG3/YWXmOnz0/FJKz+HGFds/J/VCm6uKEFA64md0Nzk21xJmFgwYM6P9MeEwTSHo= ARC-Authentication-Results: i=1; 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=ii1oimL7; arc=none smtp.client-ip=198.175.65.13 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="ii1oimL7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733437455; x=1764973455; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MSQyo461+ACp9WGYclqMonspDGXAxbE8gwEgXJXAzT0=; b=ii1oimL74P9lno1WQ94MhHO9ZZI00IVMK910VttaPI2hHrasH6S6Qowu XwmIV7zcQO3xqpH/s0rJZO6gjW0ikWCzJpc6xqf5933Cifr3oDdwhDzn6 Qt3gTA+aqHRHSRJ8lD6OhBCEQFIYUyFzb75a29CK08DVu2vyxu/u+NXo8 tclhAmIsv2oI86k9u73e1F3SLzkwPKwEUNcoQWkfuRa5m9ctYAjn0WAT8 lliXADqDW2D3RldkDkKlpN2JhtoPiL1pAcGuna4eS/J0GbVsiwXHazSsy coNTZpGF4s6lSNxpZ61O8UM0AOpkq/jABWv1RMaMAfQ5K/u1Qy5tH0FCF g==; X-CSE-ConnectionGUID: 3LGgfSGQR9iUu7sjQH3T9g== X-CSE-MsgGUID: C44q66+FTvicO+yg4TYRSg== X-IronPort-AV: E=McAfee;i="6700,10204,11277"; a="44802871" X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="44802871" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:24:15 -0800 X-CSE-ConnectionGUID: fe0Zbs9ER3exQnvrw2lNMQ== X-CSE-MsgGUID: rI+TikyZSiCjvWmwZzn4lQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="99301861" Received: from kcaccard-desk.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.125.108.178]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:24:15 -0800 Subject: [PATCH 10/11] PCI/TSM: Report active IDE streams From: Dan Williams To: linux-coco@lists.linux.dev Cc: aik@amd.com, linux-pci@vger.kernel.org, gregkh@linuxfoundation.org Date: Thu, 05 Dec 2024 14:24:14 -0800 Message-ID: <173343745420.1074769.13008006909323222504.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> References: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Given that the platform TSM owns IDE stream id allocation, report the active streams via the TSM class device. Establish a symlink from the class device to the PCI endpoint device consuming the stream, named by the stream id. Signed-off-by: Dan Williams --- Documentation/ABI/testing/sysfs-class-tsm | 10 ++++++++++ drivers/virt/coco/host/tsm-core.c | 17 +++++++++++++++++ include/linux/tsm.h | 4 ++++ 3 files changed, 31 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-tsm b/Documentation/ABI/testing/sysfs-class-tsm index 7503f04a9eb9..d6830f5f8628 100644 --- a/Documentation/ABI/testing/sysfs-class-tsm +++ b/Documentation/ABI/testing/sysfs-class-tsm @@ -8,3 +8,13 @@ Description: signals when the PCI layer is able to support establishment of link encryption and other device-security features coordinated through the platform tsm. + +What: /sys/class/tsm/tsm0/streamN:DDDDD:BB:DD:F +Date: December, 2024 +Contact: linux-pci@vger.kernel.org +Description: + (RO) When a host-bridge has established a secure connection via + the platform TSM, symlink appears. The primary function of this + is have a system global review of TSM resource consumption + across host bridges. The link points to the endpoint PCI device + at domain:DDDDD bus:BB device:DD function:F. diff --git a/drivers/virt/coco/host/tsm-core.c b/drivers/virt/coco/host/tsm-core.c index 21270210b03f..d78a9faf507d 100644 --- a/drivers/virt/coco/host/tsm-core.c +++ b/drivers/virt/coco/host/tsm-core.c @@ -2,13 +2,16 @@ /* Copyright(c) 2024 Intel Corporation. All rights reserved. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include #include #include +#include static DECLARE_RWSEM(tsm_core_rwsem); static struct class *tsm_class; @@ -100,6 +103,20 @@ void tsm_unregister(struct tsm_subsys *subsys) } EXPORT_SYMBOL_GPL(tsm_unregister); +/* must be invoked between tsm_register / tsm_unregister */ +int tsm_register_ide_stream(struct pci_dev *pdev, struct pci_ide *ide) +{ + return sysfs_create_link(&tsm_subsys->dev.kobj, &pdev->dev.kobj, + ide->name); +} +EXPORT_SYMBOL_GPL(tsm_register_ide_stream); + +void tsm_unregister_ide_stream(struct pci_ide *ide) +{ + sysfs_remove_link(&tsm_subsys->dev.kobj, ide->name); +} +EXPORT_SYMBOL_GPL(tsm_unregister_ide_stream); + static void tsm_release(struct device *dev) { struct tsm_subsys *subsys = container_of(dev, typeof(*subsys), dev); diff --git a/include/linux/tsm.h b/include/linux/tsm.h index 46b9a0c6ea4e..ce95e9130436 100644 --- a/include/linux/tsm.h +++ b/include/linux/tsm.h @@ -116,4 +116,8 @@ struct tsm_subsys *tsm_register(struct device *parent, const struct attribute_group **groups, const struct pci_tsm_ops *ops); void tsm_unregister(struct tsm_subsys *subsys); +struct pci_dev; +struct pci_ide; +int tsm_register_ide_stream(struct pci_dev *pdev, struct pci_ide *ide); +void tsm_unregister_ide_stream(struct pci_ide *ide); #endif /* __TSM_H */ From patchwork Thu Dec 5 22:24:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 13896058 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.13]) (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 3C3001CCEEC for ; Thu, 5 Dec 2024 22:24:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437461; cv=none; b=ayCh+m7tiMcnlyr6NVHczAFIMSfoPelCoXHjVGOMZol89nBPNR3/5jTYzp86SjAyhU1aPznjjuWMGvNBR8bcd5f0H6YKXsCRhRn1TwVjI2GBdzayhA5B7J0A4PtO0FqETLKU2Wn/fQ5S/LM7MvnenhylnZRkvG5wwKraaUurztY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733437461; c=relaxed/simple; bh=gQOPxSvG6K0KKylaZFce0IsL6P4x72QlIrlyr/E/AtA=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=VtQwjs9lb91JH1JEI0z4+h+ijFpYTMqHoFFX1EsUuxtrAevWG6j76NirE9DwGCBz+Q09b2kr0vVlwfueOTt+X0YQNSmriQS+mBKyxWig+m79Tp89ic6F34H6PRxw/a5dSgBgOM8u6G62NeHM+o250epBpnRA+0Dq8KvL3rdKfpo= ARC-Authentication-Results: i=1; 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=ZUg8qA5k; arc=none smtp.client-ip=198.175.65.13 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="ZUg8qA5k" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733437460; x=1764973460; h=subject:from:to:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gQOPxSvG6K0KKylaZFce0IsL6P4x72QlIrlyr/E/AtA=; b=ZUg8qA5kJAgEK4GL3FD3NsG+HI7MdtRUbTU8beKfCr73w0rLg5Hg2RkE fHLsKr8yyfuqfSMf7iOQpnKvZ+5Oo4MQaXXyhXojWKkNLHoumoBg/Oj96 R9DvZQCjazRKtbNsj4pdpeVf2XAF/d05lQ7VXfn4Iop+ngE1CPJ1kZMFc RI8OFdLn/9HjUDTrq402i3mPA36f0jGWB5Jkgk3HE9504vOdT289qQ4ST OBRXNZUPJJMhukowFor7b45IIrmZ5IN/TuUi5jX+6iw3mZmIMBtZTEIxP 8W6wKc7OGyqE29RuMDRqaXF11kI5QzOIYRebwyJlWGR6QLXBZs2Uoh01p A==; X-CSE-ConnectionGUID: zyvA6taGQeyfz/4JnMdRjg== X-CSE-MsgGUID: PWWZCo1+RXadTIANZVgCng== X-IronPort-AV: E=McAfee;i="6700,10204,11277"; a="44802885" X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="44802885" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:24:20 -0800 X-CSE-ConnectionGUID: plCRWCV5RVSWYRLX6YFPQQ== X-CSE-MsgGUID: cx9p9UcfTZK2EePkk5h3ZA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,211,1728975600"; d="scan'208";a="99301902" Received: from kcaccard-desk.amr.corp.intel.com (HELO dwillia2-xfh.jf.intel.com) ([10.125.108.178]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Dec 2024 14:24:20 -0800 Subject: [PATCH 11/11] samples/devsec: Add sample IDE establishment From: Dan Williams To: linux-coco@lists.linux.dev Cc: Bjorn Helgaas , Lukas Wunner , Samuel Ortiz , Alexey Kardashevskiy , Xu Yilun , linux-pci@vger.kernel.org, gregkh@linuxfoundation.org Date: Thu, 05 Dec 2024 14:24:19 -0800 Message-ID: <173343745958.1074769.12896997365766327404.stgit@dwillia2-xfh.jf.intel.com> In-Reply-To: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> References: <173343739517.1074769.13134786548545925484.stgit@dwillia2-xfh.jf.intel.com> User-Agent: StGit/0.18-3-g996c Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Exercise common setup and teardown flows for a sample platform TSM driver that implements the TSM 'connect' and 'disconnect' flows. This is both a template for platform specific implementations and a test case for the shared infrastructure. Cc: Bjorn Helgaas Cc: Lukas Wunner Cc: Samuel Ortiz Cc: Alexey Kardashevskiy Cc: Xu Yilun Signed-off-by: Dan Williams --- samples/devsec/tsm.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/samples/devsec/tsm.c b/samples/devsec/tsm.c index d446ab8879d8..a8894d08f323 100644 --- a/samples/devsec/tsm.c +++ b/samples/devsec/tsm.c @@ -4,11 +4,14 @@ #define dev_fmt(fmt) "devsec: " fmt #include #include +#include #include #include #include #include "devsec.h" +#define DEVSEC_NR_IDE_STREAMS 4 + struct devsec_dsm { struct pci_dsm pci; }; @@ -42,13 +45,60 @@ static void devsec_tsm_pci_remove(struct pci_dsm *dsm) kfree(devsec_dsm); } +/* protected by tsm_ops lock */ +static DECLARE_BITMAP(devsec_stream_ids, DEVSEC_NR_IDE_STREAMS); +static struct devsec_stream_info { + struct pci_dev *pdev; + struct pci_ide ide; +} devsec_streams[DEVSEC_NR_IDE_STREAMS]; + static int devsec_tsm_connect(struct pci_dev *pdev) { - return -ENXIO; + struct pci_ide *ide; + int rc, stream_id; + + stream_id = + find_first_zero_bit(devsec_stream_ids, DEVSEC_NR_IDE_STREAMS); + if (stream_id == DEVSEC_NR_IDE_STREAMS) + return -EBUSY; + set_bit(stream_id, devsec_stream_ids); + ide = &devsec_streams[stream_id].ide; + pci_ide_stream_probe(pdev, ide); + + ide->stream_id = stream_id; + rc = pci_ide_stream_setup(pdev, ide, PCI_IDE_SETUP_ROOT_PORT); + if (rc) + return rc; + rc = tsm_register_ide_stream(pdev, ide); + if (rc) + goto err; + + devsec_streams[stream_id].pdev = pdev; + pci_ide_enable_stream(pdev, ide); + return 0; +err: + pci_ide_stream_teardown(pdev, ide, PCI_IDE_SETUP_ROOT_PORT); + return rc; } static void devsec_tsm_disconnect(struct pci_dev *pdev) { + struct pci_ide *ide; + int i; + + for_each_set_bit(i, devsec_stream_ids, DEVSEC_NR_IDE_STREAMS) + if (devsec_streams[i].pdev == pdev) + break; + + if (i >= DEVSEC_NR_IDE_STREAMS) + return; + + ide = &devsec_streams[i].ide; + pci_ide_disable_stream(pdev, ide); + tsm_unregister_ide_stream(ide); + pci_ide_stream_teardown(pdev, ide, PCI_IDE_SETUP_ROOT_PORT); + devsec_streams[i].pdev = NULL; + clear_bit(i, devsec_stream_ids); } static const struct pci_tsm_ops devsec_pci_ops = { @@ -63,16 +113,44 @@ static void devsec_tsm_remove(void *tsm) tsm_unregister(tsm); } +static void set_nr_ide_streams(int nr) +{ + struct pci_dev *pdev = NULL; + + for_each_pci_dev(pdev) { + struct pci_host_bridge *hb; + + if (pdev->sysdata != devsec_sysdata) + continue; + hb = pci_find_host_bridge(pdev->bus); + if (hb->nr_ide_streams >= 0) + continue; + pci_set_nr_ide_streams(hb, nr); + } +} + +static void devsec_tsm_ide_teardown(void *data) +{ + set_nr_ide_streams(-1); +} + static int devsec_tsm_probe(struct platform_device *pdev) { struct tsm_subsys *tsm; + int rc; tsm = tsm_register(&pdev->dev, NULL, &devsec_pci_ops); if (IS_ERR(tsm)) return PTR_ERR(tsm); - return devm_add_action_or_reset(&pdev->dev, devsec_tsm_remove, - tsm); + rc = devm_add_action_or_reset(&pdev->dev, devsec_tsm_remove, tsm); + if (rc) + return rc; + + set_nr_ide_streams(DEVSEC_NR_IDE_STREAMS); + + return devm_add_action_or_reset(&pdev->dev, devsec_tsm_ide_teardown, + NULL); } static struct platform_driver devsec_tsm_driver = { @@ -109,5 +187,6 @@ static void __exit devsec_tsm_exit(void) } module_exit(devsec_tsm_exit); +MODULE_IMPORT_NS(PCI_IDE); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Device Security Sample Infrastructure: Platform TSM Driver");