[PATCH OLK-6.6 0/4] LoongArch: internal repository sync 20250528

Huacai Chen (1): LoongArch: Fix early_numa_add_cpu() usage for FDT systems Qunqin Zhao (1): tpm: Add a driver for Loongson TPM device Tianyang Zhang (2): Loongarch: Fix panic caused by NULL pmd in huge_pte_offset() mm/page_alloc.c: avoid infinite retries caused by cpuset race MAINTAINERS | 5 + arch/loongarch/configs/loongson3_defconfig | 1 + arch/loongarch/kernel/smp.c | 2 +- arch/loongarch/mm/hugetlbpage.c | 3 +- drivers/char/Kconfig | 1 + drivers/char/loongson_se.c | 33 +++++-- drivers/char/tpm/Kconfig | 9 ++ drivers/char/tpm/Makefile | 1 + drivers/char/tpm/tpm_loongson.c | 103 +++++++++++++++++++++ include/soc/loongson/se.h | 1 + mm/page_alloc.c | 8 ++ 11 files changed, 155 insertions(+), 12 deletions(-) create mode 100644 drivers/char/tpm/tpm_loongson.c -- 2.33.0

From: Qunqin Zhao <zhaoqunqin@loongson.cn> LoongArch inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICATLF CVE: NA -------------------------------- Loongson security engine supports random number generation, hash, symmetric encryption and asymmetric encryption. Based on these encryption functions, TPM2 have been implemented in the Loongson security engine firmware. This driver is responsible for copying data into the memory visible to the firmware and receiving data from the firmware. Co-developed-by: Yinggang Gu <guyinggang@loongson.cn> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn> Signed-off-by: Qunqin Zhao <zhaoqunqin@loongson.cn> Change-Id: I029740a822afd797d211a868b36e5ba8dd3b6b6a --- MAINTAINERS | 5 + arch/loongarch/configs/loongson3_defconfig | 1 + drivers/char/Kconfig | 1 + drivers/char/loongson_se.c | 33 +++++-- drivers/char/tpm/Kconfig | 9 ++ drivers/char/tpm/Makefile | 1 + drivers/char/tpm/tpm_loongson.c | 103 +++++++++++++++++++++ include/soc/loongson/se.h | 1 + 8 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 drivers/char/tpm/tpm_loongson.c diff --git a/MAINTAINERS b/MAINTAINERS index 28b2a80f6a8c..1138a6479ed8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7343,6 +7343,11 @@ F: Documentation/networking/net_dim.rst F: include/linux/dim.h F: lib/dim/ +LOONGSON TPM DRIVER +M: Qunqin Zhao <zhaoqunqin@loongson.cn> +S: Maintained +F: drivers/char/tpm/tpm_loongson.c + DYNAMIC THERMAL POWER MANAGEMENT (DTPM) M: Daniel Lezcano <daniel.lezcano@kernel.org> L: linux-pm@vger.kernel.org diff --git a/arch/loongarch/configs/loongson3_defconfig b/arch/loongarch/configs/loongson3_defconfig index 3d4c03c6b9ac..0d78f6912fe9 100644 --- a/arch/loongarch/configs/loongson3_defconfig +++ b/arch/loongarch/configs/loongson3_defconfig @@ -1148,6 +1148,7 @@ CONFIG_TCG_TIS_I2C_INFINEON=m CONFIG_TCG_TIS_I2C_NUVOTON=m CONFIG_TCG_ATMEL=m CONFIG_TCG_INFINEON=m +CONFIG_TCG_LOONGSON=m CONFIG_TCG_TIS_ST33ZP24_I2C=m CONFIG_TCG_TIS_ST33ZP24_SPI=m CONFIG_I2C_CHARDEV=y diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index ea7ace87a9df..1d2957bc100d 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -394,6 +394,7 @@ config UV_MMTIMER config LOONGSON_SE tristate "LOONGSON SECURITY MODULE Interface" depends on LOONGARCH + select MFD_CORE default m help If you have LOONGSON security module (SE) support say Yes and it diff --git a/drivers/char/loongson_se.c b/drivers/char/loongson_se.c index 853f7e10cd41..c9bd51adc792 100644 --- a/drivers/char/loongson_se.c +++ b/drivers/char/loongson_se.c @@ -14,6 +14,7 @@ #include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/mfd/core.h> #include <linux/platform_device.h> #include <soc/loongson/se.h> @@ -309,19 +310,25 @@ int se_send_ch_requeset(struct lsse_ch *ch) { struct loongson_se *se; u32 status, int_bit; + int err; se = ch->se; int_bit = ch->int_bit; + mutex_lock(&se->ch_init_lock); if ((se_readl(se, SE_L2SINT_STAT) & int_bit) || - !(se_readl(se, SE_L2SINT_EN) & int_bit)) + !(se_readl(se, SE_L2SINT_EN) & int_bit)) { + mutex_unlock(&se->ch_init_lock); return -EBUSY; + } se_enable_int(se, int_bit); se_writel(se, int_bit, SE_L2SINT_SET); - return readl_relaxed_poll_timeout_atomic(se->base + SE_L2SINT_STAT, status, + err = readl_relaxed_poll_timeout_atomic(se->base + SE_L2SINT_STAT, status, !(status & int_bit), 10, 10000); + mutex_unlock(&se->ch_init_lock); + return err; } EXPORT_SYMBOL_GPL(se_send_ch_requeset); @@ -337,10 +344,10 @@ struct lsse_ch *se_init_ch(struct device *dev, int id, int data_size, int msg_si { struct loongson_se *se = dev_get_drvdata(dev); struct lsse_ch *ch; - unsigned long flag; int data_first, data_nr; int msg_first, msg_nr; + mutex_lock(&se->ch_init_lock); if (!se) { pr_err("SE has bot been initialized\n"); return NULL; @@ -356,8 +363,6 @@ struct lsse_ch *se_init_ch(struct device *dev, int id, int data_size, int msg_si return NULL; } - spin_lock_irqsave(&se->dev_lock, flag); - ch = &se->chs[id]; ch->se = se; ch->id = id; @@ -369,7 +374,7 @@ struct lsse_ch *se_init_ch(struct device *dev, int id, int data_size, int msg_si 0, data_nr, 0); if (data_first >= se->mem_map_pages) { dev_err(se->dev, "Insufficient memory space\n"); - spin_unlock_irqrestore(&se->dev_lock, flag); + mutex_unlock(&se->ch_init_lock); return NULL; } @@ -384,7 +389,7 @@ struct lsse_ch *se_init_ch(struct device *dev, int id, int data_size, int msg_si if (msg_first >= se->mem_map_pages) { dev_err(se->dev, "Insufficient memory space\n"); bitmap_clear(se->mem_map, data_first, data_nr); - spin_unlock_irqrestore(&se->dev_lock, flag); + mutex_unlock(&se->ch_init_lock); return NULL; } @@ -396,14 +401,15 @@ struct lsse_ch *se_init_ch(struct device *dev, int id, int data_size, int msg_si ch->priv = priv; spin_lock_init(&ch->ch_lock); - spin_unlock_irqrestore(&se->dev_lock, flag); if (loongson_se_set_msg(ch)) { dev_err(se->dev, "Channel %d setup message address failed\n", id); + mutex_unlock(&se->ch_init_lock); return NULL; } se_enable_int(se, ch->int_bit); + mutex_unlock(&se->ch_init_lock); return ch; } @@ -448,6 +454,10 @@ void se_deinit_ch(struct lsse_ch *ch) } EXPORT_SYMBOL_GPL(se_deinit_ch); +static const struct mfd_cell engines[] = { + { .name = "loongson-tpm" }, +}; + static int loongson_se_probe(struct platform_device *pdev) { struct loongson_se *se; @@ -460,6 +470,7 @@ static int loongson_se_probe(struct platform_device *pdev) se->dev = dev; dev_set_drvdata(dev, se); init_completion(&se->cmd_completion); + mutex_init(&se->ch_init_lock); spin_lock_init(&se->cmd_lock); spin_lock_init(&se->dev_lock); /* Setup DMA buffer */ @@ -497,10 +508,12 @@ static int loongson_se_probe(struct platform_device *pdev) } err = se_init_hw(se, se->mem_addr, size); - if (err) + if (err) { se_disable_hw(se); + return err; + } - return err; + return devm_mfd_add_devices(dev, 0, engines, ARRAY_SIZE(engines), NULL, 0, NULL); } static const struct acpi_device_id loongson_se_acpi_match[] = { diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 301284e07603..3524b2e6086e 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -174,6 +174,15 @@ config TCG_IBMVTPM will be accessible from within Linux. To compile this driver as a module, choose M here; the module will be called tpm_ibmvtpm. +config TCG_LOONGSON + tristate "Loongson TPM Interface" + depends on LOONGSON_SE + help + If you want to make Loongson TPM support available, say Yes and + it will be accessible from within Linux. To compile this + driver as a module, choose M here; the module will be called + tpm_loongson. + config TCG_XEN tristate "XEN TPM Interface" depends on TCG_TPM && XEN diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 8f868c9b9ce7..ea2919ddbd6e 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -44,3 +44,4 @@ obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o obj-$(CONFIG_TCG_FTPM_TEE) += tpm_ftpm_tee.o obj-$(CONFIG_TCG_HYGON) += tpm_hygon.o obj-$(CONFIG_TCM_HYGON) += tcm_hygon.o +obj-$(CONFIG_TCG_LOONGSON) += tpm_loongson.o diff --git a/drivers/char/tpm/tpm_loongson.c b/drivers/char/tpm/tpm_loongson.c new file mode 100644 index 000000000000..3c27d86b77ba --- /dev/null +++ b/drivers/char/tpm/tpm_loongson.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 Loongson Technology Corporation Limited. */ + +#include <linux/device.h> +#include <soc/loongson/se.h> +#include <linux/platform_device.h> +#include <linux/wait.h> + +#include "tpm.h" + +struct tpm_loongson_msg { + u32 cmd; + u32 data_off; + u32 data_len; + u32 info[5]; +}; + +struct tpm_loongson_dev { + struct lsse_ch *se_ch; + struct completion tpm_loongson_completion; +}; + +static void tpm_loongson_complete(struct lsse_ch *ch) +{ + struct tpm_loongson_dev *td = ch->priv; + + complete(&td->tpm_loongson_completion); +} + +static int tpm_loongson_recv(struct tpm_chip *chip, u8 *buf, size_t count) +{ + struct tpm_loongson_dev *td = dev_get_drvdata(&chip->dev); + struct tpm_loongson_msg *rmsg; + int sig; + + sig = wait_for_completion_interruptible(&td->tpm_loongson_completion); + if (sig) + return sig; + + rmsg = td->se_ch->rmsg; + memcpy(buf, td->se_ch->data_buffer, rmsg->data_len); + + return rmsg->data_len; +} + +static int tpm_loongson_send(struct tpm_chip *chip, u8 *buf, size_t count) +{ + struct tpm_loongson_dev *td = dev_get_drvdata(&chip->dev); + struct tpm_loongson_msg *smsg = td->se_ch->smsg; + + memcpy(td->se_ch->data_buffer, buf, count); + smsg->data_len = count; + + return se_send_ch_requeset(td->se_ch); +} + +static const struct tpm_class_ops tpm_loongson_ops = { + .flags = TPM_OPS_AUTO_STARTUP, + .recv = tpm_loongson_recv, + .send = tpm_loongson_send, +}; + +static int tpm_loongson_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tpm_loongson_msg *smsg; + struct tpm_loongson_dev *td; + struct tpm_chip *chip; + + td = devm_kzalloc(dev, sizeof(struct tpm_loongson_dev), GFP_KERNEL); + if (!td) + return -ENOMEM; + + init_completion(&td->tpm_loongson_completion); + td->se_ch = se_init_ch(dev->parent, SE_CH_TPM, PAGE_SIZE, + 2 * sizeof(struct tpm_loongson_msg), td, + tpm_loongson_complete); + if (!td->se_ch) + return -ENODEV; + smsg = td->se_ch->smsg; + smsg->cmd = SE_CMD_TPM; + smsg->data_off = td->se_ch->data_buffer - td->se_ch->se->mem_base; + + chip = tpmm_chip_alloc(dev, &tpm_loongson_ops); + if (IS_ERR(chip)) + return PTR_ERR(chip); + chip->flags = TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_IRQ; + dev_set_drvdata(&chip->dev, td); + + return tpm_chip_register(chip); +} + +static struct platform_driver tpm_loongson_driver = { + .probe = tpm_loongson_probe, + .driver = { + .name = "loongson-tpm", + }, +}; +module_platform_driver(tpm_loongson_driver); + +MODULE_ALIAS("platform:loongson-tpm"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Loongson TPM driver"); diff --git a/include/soc/loongson/se.h b/include/soc/loongson/se.h index d9864e3f3b85..22872f7d1a19 100644 --- a/include/soc/loongson/se.h +++ b/include/soc/loongson/se.h @@ -109,6 +109,7 @@ struct loongson_se { void __iomem *base; u32 version; u32 ch_status; + struct mutex ch_init_lock; spinlock_t cmd_lock; spinlock_t dev_lock; -- 2.33.0

From: Huacai Chen <chenhuacai@loongson.cn> stable inclusion from stable-v6.6.63 commit f04125eb9eb594e35e5fad85933c5dab76d61e42 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ICB2S5 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- early_numa_add_cpu() applies on physical CPU id rather than logical CPU id, so use cpuid instead of cpu. Change-Id: Iffd70d23cfe49d580db7b0b3890b1f0a95bd822e Cc: stable@vger.kernel.org Fixes: ae9e39a2fbf5 ("LoongArch: Add all CPUs enabled by fdt to NUMA node 0") Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> Signed-off-by: Juxin Gao <gaojuxin@loongson.cn> Signed-off-by: Hongchen Zhang <zhanghongchen@loongson.cn> --- arch/loongarch/kernel/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index 78bdf81a09c5..9cdcca99467d 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -338,7 +338,7 @@ static void __init fdt_smp_setup(void) __cpu_number_map[cpuid] = cpu; __cpu_logical_map[cpu] = cpuid; - early_numa_add_cpu(cpu, 0); + early_numa_add_cpu(cpuid, 0); set_cpuid_to_node(cpuid, 0); } -- 2.33.0

From: Tianyang Zhang <zhangtianyang@loongson.cn> LoongArch inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ICB2S5 CVE: NA -------------------------------- Fixes: bd51834d1cf6 ("LoongArch: Return NULL from huge_pte_offset() for invalid PMD") ERROR INFO: CPU 25 Unable to handle kernel paging request at virtual address 0x0 ... Call Trace: [<900000000023c30c>] huge_pte_offset+0x3c/0x58 [<900000000057fd4c>] hugetlb_follow_page_mask+0x74/0x438 [<900000000051fee8>] __get_user_pages+0xe0/0x4c8 [<9000000000522414>] faultin_page_range+0x84/0x380 [<9000000000564e8c>] madvise_vma_behavior+0x534/0xa48 [<900000000056689c>] do_madvise+0x1bc/0x3e8 [<9000000000566df4>] sys_madvise+0x24/0x38 [<90000000015b9e88>] do_syscall+0x78/0x98 [<9000000000221f18>] handle_syscall+0xb8/0x158 In some cases, pmd may be NULL and rely on NULL as the return value for processing, so it is necessary to determine this situation here Signed-off-by: Tianyang Zhang <zhangtianyang@loongson.cn> Signed-off-by: Hongchen Zhang <zhanghongchen@loongson.cn> --- arch/loongarch/mm/hugetlbpage.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/loongarch/mm/hugetlbpage.c b/arch/loongarch/mm/hugetlbpage.c index aca52c42e94e..fb09fb70661e 100644 --- a/arch/loongarch/mm/hugetlbpage.c +++ b/arch/loongarch/mm/hugetlbpage.c @@ -47,7 +47,8 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr, pmd = pmd_offset(pud, addr); } } - return pmd_none(pmdp_get(pmd)) ? NULL : (pte_t *) pmd; + + return (!pmd || pmd_none(pmdp_get(pmd))) ? NULL : (pte_t *) pmd; } int pmd_huge(pmd_t pmd) -- 2.33.0

From: Tianyang Zhang <zhangtianyang@loongson.cn> mainline inclusion from mainline-v6.15 commit e05741fb10c38d70bbd7ec12b23c197b6355d519 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ICB2S5 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- __alloc_pages_slowpath has no change detection for ac->nodemask in the part of retry path, while cpuset can modify it in parallel. For some processes that set mempolicy as MPOL_BIND, this results ac->nodemask changes, and then the should_reclaim_retry will judge based on the latest nodemask and jump to retry, while the get_page_from_freelist only traverses the zonelist from ac->preferred_zoneref, which selected by a expired nodemask and may cause infinite retries in some cases cpu 64: __alloc_pages_slowpath { /* ..... */ retry: /* ac->nodemask = 0x1, ac->preferred->zone->nid = 1 */ if (alloc_flags & ALLOC_KSWAPD) wake_all_kswapds(order, gfp_mask, ac); /* cpu 1: cpuset_write_resmask update_nodemask update_nodemasks_hier update_tasks_nodemask mpol_rebind_task mpol_rebind_policy mpol_rebind_nodemask // mempolicy->nodes has been modified, // which ac->nodemask point to */ /* ac->nodemask = 0x3, ac->preferred->zone->nid = 1 */ if (should_reclaim_retry(gfp_mask, order, ac, alloc_flags, did_some_progress > 0, &no_progress_loops)) goto retry; } Simultaneously starting multiple cpuset01 from LTP can quickly reproduce this issue on a multi node server when the maximum memory pressure is reached and the swap is enabled Link: https://lkml.kernel.org/r/20250416082405.20988-1-zhangtianyang@loongson.cn Fixes: c33d6c06f60f ("mm, page_alloc: avoid looking up the first zone in a zonelist twice") Signed-off-by: Tianyang Zhang <zhangtianyang@loongson.cn> Reviewed-by: Suren Baghdasaryan <surenb@google.com> Reviewed-by: Vlastimil Babka <vbabka@suse.cz> Cc: Michal Hocko <mhocko@suse.com> Cc: Brendan Jackman <jackmanb@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Zi Yan <ziy@nvidia.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Hongchen Zhang <zhanghongchen@loongson.cn> --- mm/page_alloc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 29b03083969e..1383b3166109 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4284,6 +4284,14 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, } retry: + /* + * Deal with possible cpuset update races or zonelist updates to avoid + * infinite retries. + */ + if (check_retry_cpuset(cpuset_mems_cookie, ac) || + check_retry_zonelist(zonelist_iter_cookie)) + goto restart; + /* Ensure kswapd doesn't accidentally go to sleep as long as we loop */ if (alloc_flags & ALLOC_KSWAPD) wake_all_kswapds(order, gfp_mask, ac); -- 2.33.0

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/16500 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/MMJ... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/16500 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/MMJ...
participants (2)
-
Hongchen Zhang
-
patchwork bot