[PATCH OLK-5.10 0/4] Add some bugfix for l0.

Bugfix for L0. Wupeng Ma (4): hisi: l3t: fix conflict between HISI050 and HISI021 hisi: l3t: fix l3t unlock order hisi: l3t: use readl_poll_timeout_atomic to wait reg op finish hisi: l0: fix security risks for l0 drivers/soc/hisilicon/hisi_l0.c | 35 +++++++++++++++++++ drivers/soc/hisilicon/l3t.c | 61 +++++++++++++++++++++++++-------- 2 files changed, 81 insertions(+), 15 deletions(-) -- 2.43.0

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX -------------------------------- Since HISI021 & HISI050 use the same device, use devm_ioremap rather than devm_platform_ioremap_resource and update apci device id from HISI0501 to HISI0502 to fit this change. Fixes: c40d971092ff ("hisi: l3t: Add L3 cache driver for hisi") Signed-off-by: Wupeng Ma <mawupeng1@huawei.com> --- drivers/soc/hisilicon/l3t.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/soc/hisilicon/l3t.c b/drivers/soc/hisilicon/l3t.c index 1af1646ffbf8..0a4ceeff9da2 100644 --- a/drivers/soc/hisilicon/l3t.c +++ b/drivers/soc/hisilicon/l3t.c @@ -45,6 +45,8 @@ static int sccl_to_node_id(int id) static int hisi_l3t_init_data(struct platform_device *pdev, struct hisi_l3t *l3t) { + struct resource *mem; + if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id", &l3t->sccl_id)) return -EINVAL; @@ -53,8 +55,12 @@ static int hisi_l3t_init_data(struct platform_device *pdev, &l3t->ccl_id)) return -EINVAL; - l3t->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(l3t->base)) + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) + return -ENODEV; + + l3t->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); + if (IS_ERR_OR_NULL(l3t->base)) return PTR_ERR(l3t->base); l3t->nid = sccl_to_node_id(l3t->sccl_id); @@ -197,7 +203,7 @@ struct hisi_sccl *hisi_l3t_get_sccl(int nid) } static const struct acpi_device_id hisi_l3t_acpi_match[] = { - { "HISI0501", }, + { "HISI0502", }, {} }; MODULE_DEVICE_TABLE(acpi, hisi_l3t_acpi_match); -- 2.43.0

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX -------------------------------- Since l3t lock/unlock need different order. introduce __l3t_maintain_do_{un}lock to fit this kind of need. Fixes: c40d971092ff ("hisi: l3t: Add L3 cache driver for hisi") Signed-off-by: Wupeng Ma <mawupeng1@huawei.com> --- drivers/soc/hisilicon/l3t.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/drivers/soc/hisilicon/l3t.c b/drivers/soc/hisilicon/l3t.c index 0a4ceeff9da2..eacbb8fa3212 100644 --- a/drivers/soc/hisilicon/l3t.c +++ b/drivers/soc/hisilicon/l3t.c @@ -130,8 +130,8 @@ static void __l3t_update_and_wait(void __iomem *addr, u32 b_update, u32 b_wait) } while ((val & b_wait) == 0); } -static void __l3t_maintain(void __iomem *addr, int slot_idx, - unsigned long s_addr, int size, bool lock) +static void __l3t_maintain_do_lock(void __iomem *addr, int slot_idx, + unsigned long s_addr, int size) { if (slot_idx < 0 || slot_idx >= L3T_REG_NUM) { pr_err("slot index is invalid: %d\n", slot_idx); @@ -148,17 +148,33 @@ static void __l3t_maintain(void __iomem *addr, int slot_idx, writeq(s_addr, addr + L3T_LOCK_START_L); writel(size, addr + L3T_LOCK_AREA); - if (lock) - __l3t_update_and_wait(addr + L3T_LOCK_CTRL, LOCK_EN, LOCK_DONE); - else - __l3t_update_and_wait(addr + L3T_LOCK_CTRL, UNLOCK_EN, - UNLOCK_DONE); + __l3t_update_and_wait(addr + L3T_LOCK_CTRL, LOCK_EN, LOCK_DONE); +} + +static void __l3t_maintain_do_unlock(void __iomem *addr, int slot_idx) +{ + if (slot_idx < 0 || slot_idx >= L3T_REG_NUM) { + pr_err("slot index is invalid: %d\n", slot_idx); + return; + } + + if (!addr) { + pr_err("invalid unlock addr\n"); + return; + } + + addr += slot_idx * L3T_LOCK_STEP; + + __l3t_update_and_wait(addr + L3T_LOCK_CTRL, UNLOCK_EN, UNLOCK_DONE); + + writeq(0, addr + L3T_LOCK_START_L); + writel(0, addr + L3T_LOCK_AREA); } void hisi_l3t_lock(struct hisi_l3t *l3t, int slot_idx, unsigned long s_addr, int size) { - __l3t_maintain(l3t->base, slot_idx, s_addr, size, true); + __l3t_maintain_do_lock(l3t->base, slot_idx, s_addr, size); pr_debug("lock success. addr: %#lx, slot: %d, s_addr: %#lx, size: %#x\n", (unsigned long)l3t->base, slot_idx, s_addr, size); @@ -166,7 +182,7 @@ void hisi_l3t_lock(struct hisi_l3t *l3t, int slot_idx, unsigned long s_addr, void hisi_l3t_unlock(struct hisi_l3t *l3t, int slot_idx) { - __l3t_maintain(l3t->base, slot_idx, 0, 0, false); + __l3t_maintain_do_unlock(l3t->base, slot_idx); pr_debug("unlock success. addr: %#lx, slot: %d\n", (unsigned long)l3t->base, slot_idx); -- 2.43.0

hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX -------------------------------- Use readl_poll_timeout_atomic to wait reg op finish rather than do..while in order to avoid lockup if something is wrong during reg updating. Signed-off-by: Wupeng Ma <mawupeng1@huawei.com> --- drivers/soc/hisilicon/l3t.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/soc/hisilicon/l3t.c b/drivers/soc/hisilicon/l3t.c index eacbb8fa3212..35106e091098 100644 --- a/drivers/soc/hisilicon/l3t.c +++ b/drivers/soc/hisilicon/l3t.c @@ -15,6 +15,7 @@ #include <linux/smp.h> #include <linux/xarray.h> #include <linux/irqchip.h> +#include <linux/iopoll.h> #include "hisi_l3t.h" @@ -23,6 +24,10 @@ #define UNLOCK_EN BIT(2) #define UNLOCK_DONE BIT(3) +#define HISI_L3C_LOCK_CTRL_POLL_GAP_US 10 + +#define l3c_lock_ctrl_mask(lock_ctrl, mask) ((lock_ctrl) & (mask)) + DEFINE_MUTEX(l3t_mutex); static DEFINE_XARRAY(l3t_mapping); @@ -121,13 +126,17 @@ static int hisi_l3t_init_mapping(struct device *dev, struct hisi_l3t *l3t) /* write bit b_update and wait bit b_wait to be zero */ static void __l3t_update_and_wait(void __iomem *addr, u32 b_update, u32 b_wait) { + int timeout; u32 val; writel(b_update, addr); - do { - val = readl(addr); - } while ((val & b_wait) == 0); + timeout = readl_poll_timeout_atomic(addr, val, + l3c_lock_ctrl_mask(val, b_wait), + HISI_L3C_LOCK_CTRL_POLL_GAP_US, + jiffies_to_usecs(HZ)); + if (timeout) + pr_warn_ratelimited("read reg timeout\n"); } static void __l3t_maintain_do_lock(void __iomem *addr, int slot_idx, -- 2.43.0

hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX -------------------------------- Since vma remap or split is not supported by l0, disable these two function for l0. Add memory limit for l0_mmap to prevent users from mistakenly requesting too much memory, leading to OOM. Signed-off-by: Wupeng Ma <mawupeng1@huawei.com> --- drivers/soc/hisilicon/hisi_l0.c | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/soc/hisilicon/hisi_l0.c b/drivers/soc/hisilicon/hisi_l0.c index cc1ba59e246e..f11a9c7ac768 100644 --- a/drivers/soc/hisilicon/hisi_l0.c +++ b/drivers/soc/hisilicon/hisi_l0.c @@ -18,6 +18,9 @@ #include "hisi_l3t.h" +/* max size for l0 mmap */ +#define HISI_L0_MAX_SIZE (256UL << 20) + struct l0_vma_data { struct page *page; unsigned long size; @@ -99,9 +102,38 @@ static void l0_vma_close(struct vm_area_struct *vma) kfree(data); } +static int l0_mremap(struct vm_area_struct *vma) +{ + pr_err("mremap for l0 is not supported\n"); + + return -EINVAL; +} + +static void l0_open(struct vm_area_struct *vma) +{ + struct l0_vma_data *data; + + data = (struct l0_vma_data *)vma->vm_private_data; + if (!data) { + pr_err("%s: pid: %d, invalid private data\n", current->comm, + current->pid); + return; + } +} + +static int l0_may_split(struct vm_area_struct *vma, unsigned long addr) +{ + pr_err("L0 may not be split\n"); + + return -EINVAL; +} + static const struct vm_operations_struct l0_vm_ops = { + .open = l0_open, .huge_fault = l0_huge_fault, .close = l0_vma_close, + .split = l0_may_split, + .mremap = l0_mremap, }; static int l0_mmap(struct file *filp, struct vm_area_struct *vma) @@ -118,6 +150,9 @@ static int l0_mmap(struct file *filp, struct vm_area_struct *vma) if ((vma->vm_start % PMD_SIZE) || (vma->vm_end % PMD_SIZE)) return -EINVAL; + if (cont_size >= HISI_L0_MAX_SIZE) + return -EINVAL; + data = kzalloc(sizeof(struct l0_vma_data), GFP_KERNEL); if (!data) return -ENOMEM; -- 2.43.0

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/18474 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/Z4Y... 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/18474 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/Z4Y...
participants (2)
-
patchwork bot
-
Wupeng Ma