From 2726834315518b58e98ae709346f66a79d536f22 Mon Sep 17 00:00:00 2001 From: Ma Wupeng Date: Mon, 3 Jun 2024 16:05:11 +0800 Subject: [PATCH 1/6] export symbol alloc_contig_pages 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 --- 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) -- Gitee From 7132c7da19703411dd5a9ebb7ecd0393d4818765 Mon Sep 17 00:00:00 2001 From: Ma Wupeng Date: Mon, 3 Jun 2024 16:05:12 +0800 Subject: [PATCH 2/6] arm64: export cpu_logical_map 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 --- 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) { -- Gitee From 1c33e89afd36e39d9867f6f58aa6817061e180ee Mon Sep 17 00:00:00 2001 From: Ma Wupeng Date: Mon, 3 Jun 2024 16:05:13 +0800 Subject: [PATCH 3/6] hisi: l3t: Add L3 cache driver for hisi 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 --- drivers/soc/hisilicon/Kconfig | 9 + drivers/soc/hisilicon/Makefile | 2 + drivers/soc/hisilicon/hisi_l3t.h | 46 +++++ drivers/soc/hisilicon/hisi_lockdown.c | 142 ++++++++++++++ drivers/soc/hisilicon/l3t.c | 273 ++++++++++++++++++++++++++ 5 files changed, 472 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..c776a217b417 --- /dev/null +++ b/drivers/soc/hisilicon/hisi_lockdown.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Huawei Technologies Co., Ltd. 2024. All rights reserved. + */ + +#define pr_fmt(fmt) "hisi_l3t: " fmt + +#include +#include +#include +#include +#include + +#include "hisi_l3t.h" + +struct hisi_l3t_ops { + bool (*l3t_slot_test)(struct hisi_l3t *l3t, int slot_idx, + unsigned long addr, int size); + void (*l3t_slot_action)(struct hisi_l3t *l3t, int slot_idx, + unsigned long addr, int size); +}; + +static int hisi_l3t_sccl_action(struct hisi_sccl *sccl, unsigned long addr, + int size, struct hisi_l3t_ops *ops) +{ + struct hisi_l3t *l3t; + int i, slot_idx; + + /* + * in shared mode, all l3t belongs to one sccl is the same. + * use the first l3t to test. + */ + l3t = sccl->l3t[0]; + + mutex_lock(&l3t_mutex); + for (slot_idx = 0; slot_idx < L3T_REG_NUM; slot_idx++) { + if (ops->l3t_slot_test(l3t, slot_idx, addr, size)) + break; + } + + if (slot_idx >= L3T_REG_NUM) { + mutex_unlock(&l3t_mutex); + return -EINVAL; + } + + for (i = 0; i < sccl->ccl_cnt; i++) { + l3t = sccl->l3t[i]; + if (!l3t) + continue; + + ops->l3t_slot_action(l3t, slot_idx, addr, size); + } + mutex_unlock(&l3t_mutex); + + return 0; +} + +struct hisi_sccl *get_valid_sccl(int nid) +{ + struct hisi_sccl *sccl; + + sccl = hisi_l3t_get_sccl(nid); + if (!sccl || !sccl->ccl_cnt) + return NULL; + + if (!sccl->l3t || !sccl->l3t[0]) + return NULL; + + return sccl; +} + +static bool hisi_l3t_test_empty(struct hisi_l3t *l3t, int slot_idx, + unsigned long __always_unused addr, + int __always_unused size) +{ + unsigned long _addr; + int _size; + + hisi_l3t_read(l3t, slot_idx, &_addr, &_size); + + return _addr == 0; +} + +int l3t_shared_lock(int nid, unsigned long pfn, unsigned long size) +{ + struct hisi_l3t_ops unlock_ops = { + .l3t_slot_test = hisi_l3t_test_empty, + .l3t_slot_action = hisi_l3t_lock, + }; + struct hisi_sccl *sccl; + int ret; + + sccl = get_valid_sccl(nid); + if (!sccl) + return -ENODEV; + + ret = hisi_l3t_sccl_action(sccl, pfn << PAGE_SHIFT, size, &unlock_ops); + if (ret) + return -ENOMEM; + + return 0; +} +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; + int _size; + + hisi_l3t_read(l3t, slot_idx, &_addr, &_size); + + return (_addr == addr && _size == size); +} + +static void hisi_l3t_do_unlock(struct hisi_l3t *l3t, int slot_idx, + unsigned long __always_unused addr, + int __always_unused size) +{ + hisi_l3t_unlock(l3t, slot_idx); +} + +int l3t_shared_unlock(int nid, unsigned long pfn, unsigned long size) +{ + struct hisi_l3t_ops unlock_ops = { + .l3t_slot_test = hisi_l3t_test_equal, + .l3t_slot_action = hisi_l3t_do_unlock, + }; + struct hisi_sccl *sccl; + int ret; + + sccl = get_valid_sccl(nid); + if (!sccl) + return -ENODEV; + + ret = hisi_l3t_sccl_action(sccl, pfn << PAGE_SHIFT, size, &unlock_ops); + if (ret) + return -EINVAL; + + return 0; +} +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..9fe9da6d98dd --- /dev/null +++ b/drivers/soc/hisilicon/l3t.c @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Huawei Technologies Co., Ltd. 2024. All rights reserved. + */ + +#define pr_fmt(fmt) "hisi_l3t: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 sccl_id, cpu; + u64 mpidr; + + 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); + if (l3t->nid < 0) + return -EINVAL; + + 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; + + 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; + }; +}; + +#define LOCK_EN BIT(0) +#define LOCK_DONE BIT(1) +#define UNLOCK_EN BIT(2) +#define UNLOCK_DONE BIT(3) + +/* 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) +{ + u32 val; + + writel(b_update, addr); + + do { + val = readl(addr); + } while ((val & b_wait) == 0); +} + +static void __l3t_maintain(void __iomem *addr, int slot_idx, + unsigned long s_addr, int size, bool lock) +{ + 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; + + 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); +} + +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); + + pr_debug("lock success. addr: %#lx, slot: %d, s_addr: %#lx, size: %#x\n", + (unsigned long)l3t->base, slot_idx, s_addr, size); +} + +void hisi_l3t_unlock(struct hisi_l3t *l3t, int slot_idx) +{ + __l3t_maintain(l3t->base, slot_idx, 0, 0, false); + + pr_debug("unlock success. addr: %#lx, slot: %d\n", (unsigned long)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); +} + +struct hisi_sccl *hisi_l3t_get_sccl(int nid) +{ + return xa_load(&l3t_mapping, nid); +} + +static int __init hisi_l3t_init(void) +{ + mutex_init(&l3t_mutex); + xa_init(&l3t_mapping); + + return platform_driver_register(&hisi_l3t_driver); +} +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 "); -- Gitee From 3168787440a6beec0fa0b7ce643b94e11f203882 Mon Sep 17 00:00:00 2001 From: Ma Wupeng Date: Mon, 3 Jun 2024 16:05:14 +0800 Subject: [PATCH 4/6] mm/mempolicy: Add and export get_page_policy_node hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX -------------------------------- Function get_page_policy_node is used to return a suitable nid for order-0 page allocation. Signed-off-by: Ma Wupeng --- include/linux/mempolicy.h | 4 ++++ mm/mempolicy.c | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index d4920e4a3e38..fe7c8f9cb290 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_page_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..27099375f030 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2198,6 +2198,30 @@ static inline unsigned interleave_nid(struct mempolicy *pol, return interleave_nodes(pol); } +/* get policy node for order-0 page */ +int get_page_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_page_policy_node); + #ifdef CONFIG_HUGETLBFS /* * huge_node(@vma, @addr, @gfp_flags, @mpol) -- Gitee From 4696203f9d277e41b8e0c492877d53e578a63cd9 Mon Sep 17 00:00:00 2001 From: Ma Wupeng Date: Mon, 3 Jun 2024 16:05:15 +0800 Subject: [PATCH 5/6] hisi: l0: Add support for l0 hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9UDJX -------------------------------- L0 driver for platforms such Kunpeng 920. This provides interfaces to for user to alloc and lock memory. Signed-off-by: Ma Wupeng --- drivers/soc/hisilicon/Kconfig | 9 ++ drivers/soc/hisilicon/Makefile | 1 + drivers/soc/hisilicon/hisi_l0.c | 173 ++++++++++++++++++++++++++++++++ 3 files changed, 183 insertions(+) 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..936fc3bd5652 --- /dev/null +++ b/drivers/soc/hisilicon/hisi_l0.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Huawei Technologies Co., Ltd. 2024. All rights reserved. + */ + +#define pr_fmt(fmt) "hisi_l0: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_page_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) +{ + unsigned long pmd_addr = vmf->address & PMD_MASK; + struct l0_vma_data *data; + unsigned long pfn; + + data = vmf->vma->vm_private_data; + if (!data) { + pr_err("%s: pid: %d invalid internal data\n", current->comm, + current->pid); + return VM_FAULT_SIGBUS; + } + + if (PAGE_ALIGN(vmf->vma->vm_end - vmf->vma->vm_start) != data->size) { + pr_err("%s: pid: %d invalid vma size, start: %#lx, end: %#lx, size: %#lx\n", + current->comm, current->pid, 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; + + pfn = page_to_pfn(data->page) + + ((pmd_addr - vmf->vma->vm_start) >> PAGE_SHIFT); + + return vmf_insert_pfn_pmd(vmf, pfn_to_pfn_t(pfn), vmf->flags & FAULT_FLAG_WRITE); +} + +static vm_fault_t l0_huge_fault(struct vm_fault *vmf, + enum page_entry_size pe_size) +{ + pr_debug("%s: pid: %d %s (%#lx - %#lx) size = %d\n", current->comm, + current->pid, + (vmf->flags & FAULT_FLAG_WRITE) ? "write" : "read", + vmf->vma->vm_start, vmf->vma->vm_end, pe_size); + + if (pe_size == PE_SIZE_PMD) + return __l0_pmd_fault(vmf); + + return VM_FAULT_SIGBUS; +} + +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 | VM_DONTCOPY | 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 "); -- Gitee From da5506631a66f15be5330ec1f361c6b224386793 Mon Sep 17 00:00:00 2001 From: Ma Wupeng Date: Mon, 3 Jun 2024 16:05:16 +0800 Subject: [PATCH 6/6] arm64: config: Enable hisi l3t & l0 by default 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 --- 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 -- Gitee