From: Ma Wupeng mawupeng1@huawei.com
Add support for l3t & l0.
Ma Wupeng (6): export symbol alloc_contig_pages arm64: export cpu_logical_map hisi: l3t: Add L3 cache driver for hisi mm/mempolicy: Add and export get_policy_node hisi: l0: Add support for l0 arm64: config: Enable hisi l3t & l0 by default
arch/arm64/configs/openeuler_defconfig | 2 + arch/arm64/kernel/setup.c | 1 + drivers/soc/hisilicon/Kconfig | 18 ++ drivers/soc/hisilicon/Makefile | 3 + drivers/soc/hisilicon/hisi_l0.c | 182 +++++++++++++++ drivers/soc/hisilicon/hisi_l3t.h | 45 ++++ drivers/soc/hisilicon/hisi_lockdown.c | 138 +++++++++++ drivers/soc/hisilicon/l3t.c | 307 +++++++++++++++++++++++++ include/linux/mempolicy.h | 4 + mm/mempolicy.c | 23 ++ mm/page_alloc.c | 1 + 11 files changed, 724 insertions(+) create mode 100644 drivers/soc/hisilicon/hisi_l0.c create mode 100644 drivers/soc/hisilicon/hisi_l3t.h create mode 100644 drivers/soc/hisilicon/hisi_lockdown.c create mode 100644 drivers/soc/hisilicon/l3t.c
From: Ma Wupeng mawupeng1@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX
--------------------------------
Commit b951aaff5035 (mm: enable page allocation tagging) export alloc_contig_pages in mainline linux, in order to alloc continue page which buddy system can not handle. Export it.
Signed-off-by: Ma Wupeng mawupeng1@huawei.com --- mm/page_alloc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 1ba392f11e6b..8dc3ba5bd56c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -9356,6 +9356,7 @@ struct page *alloc_contig_pages(unsigned long nr_pages, gfp_t gfp_mask, } return NULL; } +EXPORT_SYMBOL(alloc_contig_pages); #endif /* CONFIG_CONTIG_ALLOC */
void free_contig_range(unsigned long pfn, unsigned int nr_pages)
From: Ma Wupeng mawupeng1@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX
--------------------------------
cpu_logical_map or MPIDR is used to store cpu's affinity info, export it.
Signed-off-by: Ma Wupeng mawupeng1@huawei.com --- arch/arm64/kernel/setup.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 2148f5cbb5d0..d9ce4ca603a5 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -358,6 +358,7 @@ u64 cpu_logical_map(int cpu) { return __cpu_logical_map[cpu]; } +EXPORT_SYMBOL_GPL(cpu_logical_map);
void __init __no_sanitize_address setup_arch(char **cmdline_p) {
From: Ma Wupeng mawupeng1@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX
--------------------------------
Last Level Cache driver for platforms such Kunpeng 920. This provides interfaces to enable LLC cache lockdown.
Signed-off-by: Ma Wupeng mawupeng1@huawei.com --- drivers/soc/hisilicon/Kconfig | 9 + drivers/soc/hisilicon/Makefile | 2 + drivers/soc/hisilicon/hisi_l3t.h | 46 ++++ drivers/soc/hisilicon/hisi_lockdown.c | 138 ++++++++++++ drivers/soc/hisilicon/l3t.c | 307 ++++++++++++++++++++++++++ 5 files changed, 502 insertions(+) create mode 100644 drivers/soc/hisilicon/hisi_l3t.h create mode 100644 drivers/soc/hisilicon/hisi_lockdown.c create mode 100644 drivers/soc/hisilicon/l3t.c
diff --git a/drivers/soc/hisilicon/Kconfig b/drivers/soc/hisilicon/Kconfig index 45754528873e..19c4f4602d51 100644 --- a/drivers/soc/hisilicon/Kconfig +++ b/drivers/soc/hisilicon/Kconfig @@ -54,4 +54,13 @@ config HISI_HBMDEV_ACLS
If not sure say no.
+config HISI_L3T + tristate "Add support for l3t" + depends on ARM64 && ACPI + help + Last Level Cache driver for platforms such Kunpeng 920. This provides + interfaces to enable LLC cache lockdown. + + If not sure say no. + endmenu diff --git a/drivers/soc/hisilicon/Makefile b/drivers/soc/hisilicon/Makefile index e0f966d1ed6d..022d83eccc79 100644 --- a/drivers/soc/hisilicon/Makefile +++ b/drivers/soc/hisilicon/Makefile @@ -4,3 +4,5 @@ obj-$(CONFIG_KUNPENG_HCCS) += kunpeng_hccs.o obj-$(CONFIG_HISI_HBMDEV) += hisi_hbmdev.o obj-$(CONFIG_HISI_HBMCACHE) += hisi_hbmcache.o obj-$(CONFIG_ARM64_PBHA) += pbha.o +hisi_l3t-objs := hisi_lockdown.o l3t.o +obj-$(CONFIG_HISI_L3T) += hisi_l3t.o diff --git a/drivers/soc/hisilicon/hisi_l3t.h b/drivers/soc/hisilicon/hisi_l3t.h new file mode 100644 index 000000000000..b3aebea36ae2 --- /dev/null +++ b/drivers/soc/hisilicon/hisi_l3t.h @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Huawei Technologies Co., Ltd. 2024. All rights reserved. + */ + +#ifndef _HISI_L3T_H +#define _HISI_L3T_H + +/* L3T register definition */ +#define L3T_VERSION 0x1cf0 +#define L3T_LOCK_CTRL 0x0440 +#define L3T_LOCK_AREA 0x0444 +#define L3T_LOCK_START_L 0x0448 +#define L3T_LOCK_START_H 0x044C +#define L3T_LOCK_STEP 0x10 + +#define L3T_REG_NUM 4 + +extern struct mutex l3t_mutex; + +struct hisi_l3t { + struct list_head list; + struct device *dev; + int sccl_id; + int ccl_id; + void __iomem *base; + int nid; +}; + +struct hisi_sccl { + int nid; /* numa node id */ + int ccl_cnt; /* ccl count for this sccl */ + struct hisi_l3t **l3t; +}; + +struct hisi_sccl *hisi_l3t_get_sccl(int nid); +void hisi_l3t_read(struct hisi_l3t *l3t, int slot_idx, unsigned long *s_addr, + int *size); +void hisi_l3t_lock(struct hisi_l3t *l3t, int slot_idx, unsigned long s_addr, + int size); +void hisi_l3t_unlock(struct hisi_l3t *l3t, int slot_idx); + +int l3t_shared_lock(int nid, unsigned long pfn, unsigned long size); +int l3t_shared_unlock(int nid, unsigned long pfn, unsigned long size); + +#endif diff --git a/drivers/soc/hisilicon/hisi_lockdown.c b/drivers/soc/hisilicon/hisi_lockdown.c new file mode 100644 index 000000000000..2a9bc03e04c8 --- /dev/null +++ b/drivers/soc/hisilicon/hisi_lockdown.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Huawei Technologies Co., Ltd. 2024. All rights reserved. + */ + +#define pr_fmt(fmt) "hisi_l3t: " fmt + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/kallsyms.h> +#include <linux/mm.h> + +#include "hisi_l3t.h" + +static bool hisi_l3t_test_slot_empty(struct hisi_l3t *l3t, int slot_idx) +{ + unsigned long addr; + int size; + + if (slot_idx < 0 || slot_idx >= L3T_REG_NUM) { + pr_err("slot index is invalid: %d\n", slot_idx); + return false; + } + + hisi_l3t_read(l3t, slot_idx, &addr, &size); + + return addr == 0; +} + +static int hisi_l3t_lock_sccl(struct hisi_sccl *sccl, unsigned long addr, + int size) +{ + int ccl_cnt = sccl->ccl_cnt; + int i, slot_idx; + bool empty; + struct hisi_l3t *l3t; + + if (!sccl->l3t || !sccl->l3t[0]) + return -ENODEV; + + l3t = sccl->l3t[0]; + + mutex_lock(&l3t_mutex); + for (slot_idx = 0; slot_idx < L3T_REG_NUM; slot_idx++) { + empty = hisi_l3t_test_slot_empty(l3t, slot_idx); + if (empty) + break; + } + + if (slot_idx >= L3T_REG_NUM) { + mutex_unlock(&l3t_mutex); + return -ENOMEM; + } + + for (i = 0; i < ccl_cnt; i++) { + l3t = sccl->l3t[i]; + if (!l3t) + continue; + + hisi_l3t_lock(l3t, slot_idx, addr, size); + } + mutex_unlock(&l3t_mutex); + + return 0; +} + +int l3t_shared_lock(int nid, unsigned long pfn, unsigned long size) +{ + struct hisi_sccl *sccl; + + sccl = hisi_l3t_get_sccl(nid); + if (!sccl || !sccl->ccl_cnt) + return -ENODEV; + + return hisi_l3t_lock_sccl(sccl, pfn << PAGE_SHIFT, size); +} +EXPORT_SYMBOL_GPL(l3t_shared_lock); + +static bool hisi_l3t_test_equal(struct hisi_l3t *l3t, int slot_idx, + unsigned long addr, int size) +{ + unsigned long addr_inner; + int size_inner; + + hisi_l3t_read(l3t, slot_idx, &addr_inner, &size_inner); + + return (addr_inner == addr && size_inner == size); +} + +static int hisi_l3t_unlock_sccl(struct hisi_sccl *sccl, unsigned long addr, + int size) +{ + int ccl_cnt = sccl->ccl_cnt; + int slot_idx, i; + bool equal; + struct hisi_l3t *l3t; + + if (!sccl->l3t || !sccl->l3t[0]) + return -ENODEV; + + l3t = sccl->l3t[0]; + + mutex_lock(&l3t_mutex); + for (slot_idx = 0; slot_idx < L3T_REG_NUM; slot_idx++) { + equal = hisi_l3t_test_equal(l3t, slot_idx, addr, size); + if (equal) + break; + } + + if (slot_idx >= L3T_REG_NUM) { + mutex_unlock(&l3t_mutex); + return -EINVAL; + } + + for (i = 0; i < ccl_cnt; i++) { + l3t = sccl->l3t[i]; + if (!l3t) + continue; + + hisi_l3t_unlock(l3t, slot_idx); + } + mutex_unlock(&l3t_mutex); + + return 0; +} + +int l3t_shared_unlock(int nid, unsigned long pfn, unsigned long size) +{ + struct hisi_sccl *sccl; + + sccl = hisi_l3t_get_sccl(nid); + if (!sccl || !sccl->ccl_cnt) + return -ENODEV; + + return hisi_l3t_unlock_sccl(sccl, pfn << PAGE_SHIFT, size); +} +EXPORT_SYMBOL_GPL(l3t_shared_unlock); diff --git a/drivers/soc/hisilicon/l3t.c b/drivers/soc/hisilicon/l3t.c new file mode 100644 index 000000000000..b6be3c6f5efe --- /dev/null +++ b/drivers/soc/hisilicon/l3t.c @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Huawei Technologies Co., Ltd. 2024. All rights reserved. + */ + +#define pr_fmt(fmt) "hisi_l3t: " fmt + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/kallsyms.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/smp.h> +#include <linux/xarray.h> +#include <linux/irqchip.h> + +#include "hisi_l3t.h" + +DEFINE_MUTEX(l3t_mutex); +static DEFINE_XARRAY(l3t_mapping); + +static const struct acpi_device_id hisi_l3t_acpi_match[] = { + { "HISI0501", }, + {} +}; +MODULE_DEVICE_TABLE(acpi, hisi_l3t_acpi_match); + +static int sccl_to_node_id(int id) +{ + int cpu; + u64 mpidr; + int sccl_id; + + for_each_possible_cpu(cpu) { + mpidr = cpu_logical_map(cpu); + sccl_id = MPIDR_AFFINITY_LEVEL(mpidr, 3); + if (sccl_id == id) + return cpu_to_node(cpu); + } + + pr_err("invalid sccl id: %d\n", id); + return -EINVAL; +} + +static int hisi_l3t_init_data(struct platform_device *pdev, + struct hisi_l3t *l3t) +{ + if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id", + &l3t->sccl_id)) + return -EINVAL; + + if (device_property_read_u32(&pdev->dev, "hisilicon,ccl-id", + &l3t->ccl_id)) + return -EINVAL; + + l3t->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(l3t->base)) + return PTR_ERR(l3t->base); + + l3t->nid = sccl_to_node_id(l3t->sccl_id); + + pr_info("sccl id: %d ccl id: %d, nid: %d, base: %#lx\n", l3t->sccl_id, + l3t->ccl_id, l3t->nid, (unsigned long)l3t->base); + + return 0; +} + +static int hisi_l3t_insert_to_sccl(struct hisi_sccl *sccl, struct hisi_l3t *l3t) +{ + void *tmp_l3t; + + if (sccl->ccl_cnt < l3t->ccl_id) + goto set; + + tmp_l3t = krealloc(sccl->l3t, + (l3t->ccl_id + 1) * sizeof(struct hisi_l3t *), + GFP_KERNEL); + if (!tmp_l3t) + return -ENOMEM; + + sccl->ccl_cnt = l3t->ccl_id + 1; + sccl->l3t = tmp_l3t; + +set: + sccl->l3t[l3t->ccl_id] = l3t; + return 0; +} + +/* + * Use xarray to store the mapping b/t nid to sccl + * all ccls belong be one sccl is store with vla in sccl->l3t + */ +static int hisi_l3t_init_mapping(struct device *dev, struct hisi_l3t *l3t) +{ + struct hisi_sccl *sccl; + int ret = -ENOMEM; + + mutex_lock(&l3t_mutex); + sccl = xa_load(&l3t_mapping, l3t->nid); + if (!sccl) { + sccl = devm_kzalloc(dev, sizeof(*sccl), GFP_KERNEL); + if (!sccl) + goto unlock; + sccl->nid = l3t->nid; + + xa_store(&l3t_mapping, l3t->nid, sccl, GFP_KERNEL); + } + + ret = hisi_l3t_insert_to_sccl(sccl, l3t); +unlock: + mutex_unlock(&l3t_mutex); + + return ret; +} + +static int hisi_l3t_probe(struct platform_device *pdev) +{ + struct hisi_l3t *l3t; + int ret = -ENOMEM; + + l3t = devm_kzalloc(&pdev->dev, sizeof(*l3t), GFP_KERNEL); + if (!l3t) + return -ENOMEM; + + platform_set_drvdata(pdev, l3t); + + ret = hisi_l3t_init_data(pdev, l3t); + if (!ret) { + l3t->dev = &pdev->dev; + ret = hisi_l3t_init_mapping(&pdev->dev, l3t); + } + + return ret; +} + +static struct platform_driver hisi_l3t_driver = { + .driver = { + .name = "hisi_l3t", + .acpi_match_table = ACPI_PTR(hisi_l3t_acpi_match), + .suppress_bind_attrs = true, + }, + .probe = hisi_l3t_probe, +}; + +struct l3t_lock_ctrl { + union { + unsigned int u32; + struct { + unsigned int lock_en : 1; + unsigned int lock_done : 1; + unsigned int unlock_en : 1; + unsigned int unlock_done : 1; + } bits; + }; +}; + +static void l3t_lock(void __iomem *addr, int slot_idx, unsigned long s_addr, + int size) +{ + struct l3t_lock_ctrl ctrl; + + if (!addr) { + pr_err("invalid lock addr\n"); + return; + } + + writeq(s_addr, addr + L3T_LOCK_START_L + slot_idx * L3T_LOCK_STEP); + writel(size, addr + L3T_LOCK_AREA + slot_idx * L3T_LOCK_STEP); + + ctrl.u32 = 0; + ctrl.bits.lock_en = 1; + ctrl.bits.unlock_en = 0; + writel(ctrl.u32, addr + L3T_LOCK_CTRL + slot_idx * L3T_LOCK_STEP); + + do { + ctrl.u32 = + readl(addr + L3T_LOCK_CTRL + slot_idx * L3T_LOCK_STEP); + } while (ctrl.bits.lock_done == 0); + + pr_debug("lock success. addr: %#lx, s_addr: %#lx, size: %#x\n", + (unsigned long)addr + L3T_LOCK_START_L + + slot_idx * L3T_LOCK_STEP, + s_addr, size); +} + +static void l3t_unlock(void __iomem *addr, int slot_idx) +{ + struct l3t_lock_ctrl ctrl; + + if (!addr) { + pr_err("invalid unlock addr\n"); + return; + } + + writeq(0, addr + L3T_LOCK_START_L + slot_idx * L3T_LOCK_STEP); + writel(0, addr + L3T_LOCK_AREA + slot_idx * L3T_LOCK_STEP); + + ctrl.u32 = 0; + + ctrl.bits.unlock_en = 1; + ctrl.bits.lock_en = 0; + writel(ctrl.u32, addr + L3T_LOCK_CTRL + slot_idx * L3T_LOCK_STEP); + + do { + ctrl.u32 = + readl(addr + L3T_LOCK_CTRL + slot_idx * L3T_LOCK_STEP); + } while (ctrl.bits.unlock_done == 0); + + pr_debug("unlock success. addr: %#lx\n", + (unsigned long)addr + L3T_LOCK_START_L + + slot_idx * L3T_LOCK_STEP); +} + +void hisi_l3t_unlock(struct hisi_l3t *l3t, int slot_idx) +{ + if (slot_idx < 0 || slot_idx >= L3T_REG_NUM) { + pr_err("slot index is invalid: %d\n", slot_idx); + return; + } + + l3t_unlock(l3t->base, slot_idx); +} + +static void hisi_l3t_read_inner(void __iomem *addr, int locksel, + unsigned long *s_addr, int *size) +{ + if (!addr) { + *s_addr = 0; + *size = 0; + pr_err("invalid unlock addr\n"); + return; + } + + *s_addr = readq(addr + L3T_LOCK_START_L + locksel * L3T_LOCK_STEP); + *size = readl(addr + L3T_LOCK_AREA + locksel * L3T_LOCK_STEP); +} + +void hisi_l3t_read(struct hisi_l3t *l3t, 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); + return; + } + + return hisi_l3t_read_inner(l3t->base, slot_idx, s_addr, size); +} + +void hisi_l3t_lock(struct hisi_l3t *l3t, int slot_idx, unsigned long s_addr, + int size) +{ + if (!s_addr) { + pr_err("invalid start addr\n"); + return; + } + + if (slot_idx < 0 || slot_idx >= L3T_REG_NUM) { + pr_err("invalid slot index: %d\n", slot_idx); + return; + } + + l3t_lock(l3t->base, slot_idx, s_addr, size); +} + +struct hisi_sccl *hisi_l3t_get_sccl(int nid) +{ + return xa_load(&l3t_mapping, nid); +} + +static int __init hisi_l3t_init(void) +{ + int ret; + + mutex_init(&l3t_mutex); + xa_init(&l3t_mapping); + + ret = platform_driver_register(&hisi_l3t_driver); + if (ret) + return ret; + + return 0; +} +module_init(hisi_l3t_init); + +static void hisi_l3t_destroy_sccl(void) +{ + struct hisi_sccl *sccl; + unsigned long nid; + + xa_for_each(&l3t_mapping, nid, sccl) + kfree(sccl->l3t); +} + +static void __exit hisi_l3t_exit(void) +{ + hisi_l3t_destroy_sccl(); + xa_destroy(&l3t_mapping); + + platform_driver_unregister(&hisi_l3t_driver); +} +module_exit(hisi_l3t_exit); + +MODULE_DESCRIPTION("HiSilicon SoC L3T driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Ma Wupeng mawupeng1@huawei.com");
From: Ma Wupeng mawupeng1@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX
--------------------------------
Function get_policy_node is used to return a suitable nid for memory allocation.
Signed-off-by: Ma Wupeng mawupeng1@huawei.com --- include/linux/mempolicy.h | 4 ++++ mm/mempolicy.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+)
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index d4920e4a3e38..c758d2408cfe 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -161,6 +161,10 @@ extern nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *policy);
extern unsigned int mempolicy_slab_node(void);
+int get_policy_node(struct vm_area_struct *vma, unsigned long addr, + gfp_t gfp_flags, struct mempolicy **mpol, + nodemask_t **nodemask); + extern enum zone_type policy_zone;
static inline void check_highest_zone(enum zone_type k) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 81bd26fb661f..c8f389f194f9 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2198,6 +2198,29 @@ static inline unsigned interleave_nid(struct mempolicy *pol, return interleave_nodes(pol); }
+int get_policy_node(struct vm_area_struct *vma, unsigned long addr, + gfp_t gfp_flags, struct mempolicy **mpol, + nodemask_t **nodemask) +{ + int nid; + int mode; + + *mpol = get_vma_policy(vma, addr); + *nodemask = NULL; + mode = (*mpol)->mode; + + if (unlikely(mode == MPOL_INTERLEAVE)) { + nid = interleave_nid(*mpol, vma, addr, PAGE_SHIFT); + } else { + nid = policy_node(gfp_flags, *mpol, numa_node_id()); + if ((*mpol)->mode == MPOL_BIND || mode == MPOL_PREFERRED_MANY) + *nodemask = &(*mpol)->v.nodes; + } + + return nid; +} +EXPORT_SYMBOL_GPL(get_policy_node); + #ifdef CONFIG_HUGETLBFS /* * huge_node(@vma, @addr, @gfp_flags, @mpol)
From: Ma Wupeng mawupeng1@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX
--------------------------------
Signed-off-by: Ma Wupeng mawupeng1@huawei.com --- drivers/soc/hisilicon/Kconfig | 9 ++ drivers/soc/hisilicon/Makefile | 1 + drivers/soc/hisilicon/hisi_l0.c | 182 +++++++++++++++++++++++++++++++ drivers/soc/hisilicon/hisi_l3t.h | 1 - 4 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/hisilicon/hisi_l0.c
diff --git a/drivers/soc/hisilicon/Kconfig b/drivers/soc/hisilicon/Kconfig index 19c4f4602d51..90d8036ae658 100644 --- a/drivers/soc/hisilicon/Kconfig +++ b/drivers/soc/hisilicon/Kconfig @@ -63,4 +63,13 @@ config HISI_L3T
If not sure say no.
+config HISI_L0 + tristate "Add support L0 cache" + depends on ARM64 && HISI_L3T + help + L0 driver for platforms such Kunpeng 920. This provides interfaces to + for user to alloc and lock memory + + If not sure say no. + endmenu diff --git a/drivers/soc/hisilicon/Makefile b/drivers/soc/hisilicon/Makefile index 022d83eccc79..d91b8ed30306 100644 --- a/drivers/soc/hisilicon/Makefile +++ b/drivers/soc/hisilicon/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_HISI_HBMCACHE) += hisi_hbmcache.o obj-$(CONFIG_ARM64_PBHA) += pbha.o hisi_l3t-objs := hisi_lockdown.o l3t.o obj-$(CONFIG_HISI_L3T) += hisi_l3t.o +obj-$(CONFIG_HISI_L0) += hisi_l0.o diff --git a/drivers/soc/hisilicon/hisi_l0.c b/drivers/soc/hisilicon/hisi_l0.c new file mode 100644 index 000000000000..671f1253f587 --- /dev/null +++ b/drivers/soc/hisilicon/hisi_l0.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Huawei Technologies Co., Ltd. 2024. All rights reserved. + */ + +#define pr_fmt(fmt) "hisi_l0: " fmt + +#include <linux/fs.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/miscdevice.h> +#include <linux/kallsyms.h> +#include <linux/mm.h> +#include <linux/gfp.h> +#include <linux/mempolicy.h> +#include <linux/pfn_t.h> + +#include "hisi_l3t.h" + +struct l0_vma_data { + struct page *page; + unsigned long size; + int nid; +}; + +static int get_node_node(struct vm_area_struct *vma) +{ + struct mempolicy *pol; + nodemask_t *nmask; + int nid; + + nid = get_policy_node(vma, vma->vm_start, GFP_KERNEL, &pol, &nmask); + if (pol->mode == MPOL_BIND || pol->mode == MPOL_PREFERRED_MANY) + nid = first_node(*nmask); + + return nid; +} + +static vm_fault_t __l0_pmd_fault(struct vm_fault *vmf, pfn_t *pfn) +{ + unsigned long pmd_addr = vmf->address & PMD_MASK; + struct l0_vma_data *data; + unsigned long page_pfn; + + data = vmf->vma->vm_private_data; + if (!data) { + pr_err("invalid internal data\n"); + return VM_FAULT_SIGBUS; + } + + if (PAGE_ALIGN(vmf->vma->vm_end - vmf->vma->vm_start) != data->size) { + pr_err("invalid vma size, start: %#lx, end: %#lx, size: %#lx\n", + vmf->vma->vm_start, vmf->vma->vm_end, data->size); + return VM_FAULT_SIGBUS; + } + + /* if we are outside of the VMA */ + if (pmd_addr < vmf->vma->vm_start || + (pmd_addr + PMD_SIZE) > vmf->vma->vm_end) + return VM_FAULT_SIGBUS; + + page_pfn = page_to_pfn(data->page) + + ((pmd_addr - vmf->vma->vm_start) >> PAGE_SHIFT); + + *pfn = pfn_to_pfn_t(page_pfn); + + return vmf_insert_pfn_pmd(vmf, *pfn, vmf->flags & FAULT_FLAG_WRITE); +} + +static vm_fault_t l0_huge_fault(struct vm_fault *vmf, + enum page_entry_size pe_size) +{ + vm_fault_t rc; + pfn_t pfn; + + pr_debug("%s: %s (%#lx - %#lx) size = %d\n", current->comm, + (vmf->flags & FAULT_FLAG_WRITE) ? "write" : "read", + vmf->vma->vm_start, vmf->vma->vm_end, pe_size); + + switch (pe_size) { + case PE_SIZE_PMD: + rc = __l0_pmd_fault(vmf, &pfn); + break; + default: + pr_err("invalid fault size: %d\n", pe_size); + rc = VM_FAULT_SIGBUS; + } + + return rc; +} + +static void l0_vma_close(struct vm_area_struct *vma) +{ + struct l0_vma_data *data; + + data = (struct l0_vma_data *)vma->vm_private_data; + if (!data) { + pr_err("invalid internal data\n"); + return; + } + + l3t_shared_unlock(data->nid, page_to_pfn(data->page), data->size); + free_contig_range(page_to_pfn(data->page), data->size >> PAGE_SHIFT); + + kfree(data); +} + +static const struct vm_operations_struct l0_vm_ops = { + .huge_fault = l0_huge_fault, + .close = l0_vma_close, +}; + +static int l0_mmap(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long cont_size = PAGE_ALIGN(vma->vm_end - vma->vm_start); + struct l0_vma_data *data; + int page_cnt, nid, ret; + struct page *page; + + pr_debug("vma_start: %#lx, vma_end: %#lx vma_flags: %pGv\n", + vma->vm_start, vma->vm_end, &vma->vm_flags); + + if ((vma->vm_start % PMD_SIZE) || (vma->vm_end % PMD_SIZE)) { + pr_err("vma addr should align PMD_SIZE\n"); + return -EINVAL; + } + + data = kzalloc(sizeof(struct l0_vma_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + page_cnt = cont_size >> PAGE_SHIFT; + + nid = get_node_node(vma); + + page = alloc_contig_pages(page_cnt, GFP_KERNEL, nid, NULL); + if (!page) { + pr_err("alloc continue memory failed, size: %#lx\n", cont_size); + ret = -ENOMEM; + goto free_data; + } + + ret = l3t_shared_lock(nid, page_to_pfn(page), cont_size); + if (ret) { + pr_err("l3t lock failed, ret: %d\n", ret); + ret = -ENOMEM; + goto free_page; + } + + data->page = page; + data->size = cont_size; + data->nid = nid; + + vma->vm_ops = &l0_vm_ops; + vma->vm_flags |= VM_MIXEDMAP; + vma->vm_flags |= VM_DONTCOPY; + vma->vm_flags |= VM_DONTEXPAND; + vma->vm_private_data = data; + + return 0; +free_page: + free_contig_range(page_to_pfn(page), page_cnt); +free_data: + kfree(data); + return ret; +} + +static const struct file_operations l0_fops = { + .mmap = l0_mmap, +}; + +static struct miscdevice l0_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "hisi_l0", + .fops = &l0_fops, +}; +module_misc_device(l0_dev); + +MODULE_DESCRIPTION("HiSilicon SoC L0 driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Ma Wupeng mawupeng1@huawei.com"); diff --git a/drivers/soc/hisilicon/hisi_l3t.h b/drivers/soc/hisilicon/hisi_l3t.h index b3aebea36ae2..53d6d774f94c 100644 --- a/drivers/soc/hisilicon/hisi_l3t.h +++ b/drivers/soc/hisilicon/hisi_l3t.h @@ -42,5 +42,4 @@ void hisi_l3t_unlock(struct hisi_l3t *l3t, int slot_idx);
int l3t_shared_lock(int nid, unsigned long pfn, unsigned long size); int l3t_shared_unlock(int nid, unsigned long pfn, unsigned long size); - #endif
From: Ma Wupeng mawupeng1@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX
--------------------------------
Enable hisi l3t & l0 for arm64 by default.
Signed-off-by: Ma Wupeng mawupeng1@huawei.com --- arch/arm64/configs/openeuler_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index a83bf85e289b..dd553b7d2b6e 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -6107,6 +6107,8 @@ CONFIG_QCOM_KRYO_L2_ACCESSORS=y CONFIG_KUNPENG_HCCS=m # CONFIG_HISI_HBMDEV is not set # CONFIG_HISI_HBMCACHE is not set +CONFIG_HISI_L3T=m +CONFIG_HISI_L0=m # end of Hisilicon SoC drivers # end of SOC (System On Chip) specific Drivers
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/8459 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/K...
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/8459 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/K...