Kernel
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- 48 participants
- 19096 discussions

17 Mar '21
From: Zhang Ming <154842638(a)qq.com>
[PATCH v1 openEuler-21.03]arch/arm64/kernel/mpam/mpam_ctrlmon.c: fix a bug of memory leakage
openEuler inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I3BPPX
CVE: NA
-----------------------------------------------------------
The default branch in switch will not run at present, but there may be related extensions in the future, which may lead to memory leakage
Signed-off-by: Zhang Ming <154842638(a)qq.com>
Reported-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
Suggested-by: Jian Cheng <cj.chengjian(a)huawei.com>
---
arch/arm64/kernel/mpam/mpam_ctrlmon.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/mpam/mpam_ctrlmon.c b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
index 4acf9234c3a5..b1d32d432556 100644
--- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c
+++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
@@ -74,6 +74,7 @@ static int add_schema(enum resctrl_conf_type t, struct resctrl_resource *r)
suffix = "";
break;
default:
+ kfree(s);
return -EINVAL;
}
--
2.17.1
1
0
From: Zhang Ming <154842638(a)qq.com>
[PATCH kernel-4.19]arch/arm64/kernel/mpam/mpam_ctrlmon.c: fix a bug of memory leakage
openEuler inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I3BPPX
CVE: NA
-----------------------------------------------------------
The default branch in switch will not run at present, but there may be related extensions in the future, which may lead to memory leakage
Signed-off-by: Zhang Ming <154842638(a)qq.com>
Reported-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
Suggested-by: Jian Cheng <cj.chengjian(a)huawei.com>
---
arch/arm64/kernel/mpam/mpam_ctrlmon.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/mpam/mpam_ctrlmon.c b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
index aae585e7d7df..a4a298a455e0 100644
--- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c
+++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c
@@ -78,6 +78,7 @@ static int add_schema(enum resctrl_conf_type t, struct resctrl_resource *r)
suffix = "";
break;
default:
+ kfree(s);
return -EINVAL;
}
--
2.17.1
1
0
1
0
CVE for openEuler 20.09
Chris Leech (2):
scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE
scsi: iscsi: Verify lengths on passthrough PDUs
Jan Beulich (10):
Xen/x86: don't bail early from clear_foreign_p2m_mapping()
Xen/x86: also check kernel mapping in set_foreign_p2m_mapping()
Xen/gntdev: correct dev_bus_addr handling in gntdev_map_grant_pages()
Xen/gntdev: correct error checking in gntdev_map_grant_pages()
xen-blkback: don't "handle" error by BUG()
xen-netback: don't "handle" error by BUG()
xen-scsiback: don't "handle" error by BUG()
xen-blkback: fix error handling in xen_blkbk_map()
Xen/gnttab: handle p2m update errors on a per-slot basis
xen-netback: respect gnttab_map_refs()'s return value
Joe Perches (1):
sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output
Lee Duncan (1):
scsi: iscsi: Restrict sessions and handles to admin capabilities
Miklos Szeredi (6):
ovl: pass correct flags for opening real directory
ovl: switch to mounter creds in readdir
ovl: verify permissions in ovl_path_open()
ovl: call secutiry hook in ovl_real_ioctl()
ovl: check permission to open real file
ovl: do not fail because of O_NOATIME
Stefano Stabellini (1):
xen/arm: don't ignore return errors from set_phys_to_machine
Wenchao Hao (1):
virtio-blk: modernize sysfs attribute creation
Yang Yingliang (1):
sysfs: fix kabi broken when add sysfs_emit and sysfs_emit_at
Documentation/filesystems/sysfs.txt | 8 +-
arch/arm/xen/p2m.c | 33 ++++++-
arch/x86/xen/p2m.c | 59 ++++++++---
drivers/block/virtio_blk.c | 67 +++++++------
drivers/block/xen-blkback/blkback.c | 30 +++---
drivers/net/xen-netback/netback.c | 10 +-
drivers/scsi/libiscsi.c | 148 ++++++++++++++--------------
drivers/scsi/scsi_transport_iscsi.c | 38 +++++--
drivers/xen/gntdev.c | 37 +++----
drivers/xen/xen-scsiback.c | 4 +-
fs/overlayfs/file.c | 28 ++++--
fs/overlayfs/readdir.c | 37 +++++--
fs/overlayfs/util.c | 27 ++++-
fs/sysfs/file.c | 55 +++++++++++
include/linux/sysfs.h | 16 +++
include/xen/grant_table.h | 1 +
security/security.c | 1 +
17 files changed, 419 insertions(+), 180 deletions(-)
--
2.25.1
2
24
CVE-2021-27365
CVE-2021-27363
CVE-2021-27364
Chris Leech (2):
scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE
scsi: iscsi: Verify lengths on passthrough PDUs
Christoph Hellwig (1):
mm/swapfile.c: fix a comment in sys_swapon()
Darrick J. Wong (2):
mm: set S_SWAPFILE on blockdev swap devices
vfs: don't allow writes to swap files
Domenico Andreoli (1):
hibernate: Allow uswsusp to write to swap
Jan Beulich (10):
Xen/x86: don't bail early from clear_foreign_p2m_mapping()
Xen/x86: also check kernel mapping in set_foreign_p2m_mapping()
Xen/gntdev: correct dev_bus_addr handling in gntdev_map_grant_pages()
Xen/gntdev: correct error checking in gntdev_map_grant_pages()
xen-blkback: don't "handle" error by BUG()
xen-netback: don't "handle" error by BUG()
xen-scsiback: don't "handle" error by BUG()
xen-blkback: fix error handling in xen_blkbk_map()
Xen/gnttab: handle p2m update errors on a per-slot basis
xen-netback: respect gnttab_map_refs()'s return value
Joe Perches (1):
sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output
Lee Duncan (1):
scsi: iscsi: Restrict sessions and handles to admin capabilities
Miaohe Lin (1):
mm/swapfile.c: fix potential memory leak in sys_swapon
Miklos Szeredi (6):
ovl: pass correct flags for opening real directory
ovl: switch to mounter creds in readdir
ovl: verify permissions in ovl_path_open()
ovl: call secutiry hook in ovl_real_ioctl()
ovl: check permission to open real file
ovl: do not fail because of O_NOATIME
Naohiro Aota (1):
mm/swapfile.c: move inode_lock out of claim_swapfile
Stefano Stabellini (1):
xen/arm: don't ignore return errors from set_phys_to_machine
Wenchao Hao (2):
nvme: register ns_id attributes as default sysfs groups
virtio-blk: modernize sysfs attribute creation
Yang Yingliang (1):
sysfs: fix kabi broken when add sysfs_emit and sysfs_emit_at
Ye Bin (1):
ext4: Fix not report exception message when mount with errors=continue
zhangyi (F) (1):
block_dump: remove block_dump feature when dirting inode
Documentation/filesystems/sysfs.txt | 8 +-
arch/arm/xen/p2m.c | 33 ++++++-
arch/x86/xen/p2m.c | 59 ++++++++---
drivers/block/virtio_blk.c | 67 +++++++------
drivers/block/xen-blkback/blkback.c | 30 +++---
drivers/net/xen-netback/netback.c | 10 +-
drivers/nvme/host/core.c | 20 ++--
drivers/nvme/host/lightnvm.c | 105 +++++++++-----------
drivers/nvme/host/multipath.c | 11 +--
drivers/nvme/host/nvme.h | 10 +-
drivers/scsi/libiscsi.c | 148 ++++++++++++++--------------
drivers/scsi/scsi_transport_iscsi.c | 38 +++++--
drivers/xen/gntdev.c | 37 +++----
drivers/xen/xen-scsiback.c | 4 +-
fs/block_dev.c | 5 +
fs/ext4/super.c | 6 +-
fs/fs-writeback.c | 25 -----
fs/overlayfs/file.c | 28 ++++--
fs/overlayfs/readdir.c | 37 +++++--
fs/overlayfs/util.c | 27 ++++-
fs/sysfs/file.c | 55 +++++++++++
include/linux/fs.h | 11 +++
include/linux/sysfs.h | 16 +++
include/xen/grant_table.h | 1 +
mm/filemap.c | 3 +
mm/memory.c | 4 +
mm/mmap.c | 8 +-
mm/swapfile.c | 72 ++++++++------
security/security.c | 1 +
29 files changed, 552 insertions(+), 327 deletions(-)
--
2.25.1
1
32

12 Mar '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
------------------------------
One cpu in PARK state could not come up in this case:
CPU 0 | CPU 1
boot_secondary(cpu 1) |
--> write_park_exit(cpu 1) |
| cpu uping from PARK
| ...
uninstall_cpu_park() |
--> memset to 0 park text |
| ...
| Exception in memory !!
wait for cpu up |
Cpu 1 uping from PARK may trap into exception while cpu 0
clear cpu 1's park text memory.
This uninstall_cpu_park should be after waiting for cpu up.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/arm64/kernel/smp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index d7b750a..fb6007d 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -300,15 +300,15 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
return ret;
}
-#ifdef CONFIG_ARM64_CPU_PARK
- uninstall_cpu_park(cpu);
-#endif
/*
* CPU was successfully started, wait for it to come online or
* time out.
*/
wait_for_completion_timeout(&cpu_running,
msecs_to_jiffies(5000));
+#ifdef CONFIG_ARM64_CPU_PARK
+ uninstall_cpu_park(cpu);
+#endif
if (cpu_online(cpu))
return 0;
--
2.9.5
2
1

12 Mar '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
------------------------------
One cpu in PARK state could not come up in this case:
CPU 0 | CPU 1
boot_secondary(cpu 1) |
--> write_park_exit(cpu 1) |
| cpu uping from PARK
| ...
uninstall_cpu_park() |
--> memset to 0 park text |
| ...
| Exception in memory !!
wait for cpu up |
Cpu 1 uping from PARK may trap into exception while cpu 0
clear cpu 1's park text memory.
This uninstall_cpu_park should be after waiting for cpu up.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/arm64/kernel/smp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index d7b750a..fb6007d 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -300,15 +300,15 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
return ret;
}
-#ifdef CONFIG_ARM64_CPU_PARK
- uninstall_cpu_park(cpu);
-#endif
/*
* CPU was successfully started, wait for it to come online or
* time out.
*/
wait_for_completion_timeout(&cpu_running,
msecs_to_jiffies(5000));
+#ifdef CONFIG_ARM64_CPU_PARK
+ uninstall_cpu_park(cpu);
+#endif
if (cpu_online(cpu))
return 0;
--
2.9.5
1
0

[PATCH openEuler-21.03 v2] park: Reserve park mem before kexec reserved
by sangyan@huawei.com 12 Mar '21
by sangyan@huawei.com 12 Mar '21
12 Mar '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
------------------------------
reserve_crashkernel or reserve_quick_kexec may find one sutiable
memory region and reserves it, which address of the region is
not fixed.
As a result, cpu park reserves memory could be failed while
specified address used by crashkernel or quickkexec.
So, move reserve_park_mem before reserve_crashkernel and
reserve_quick_kexec.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
Reviewed-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
---
arch/arm64/mm/init.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b343744..dbcc801 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -497,16 +497,25 @@ void __init arm64_memblock_init(void)
else
arm64_dma32_phys_limit = PHYS_MASK + 1;
+ /*
+ * Reserve park memory before crashkernel and quick kexec.
+ * Because park memory must be specified by address, but
+ * crashkernel and quickkexec may be specified by memory length,
+ * then find one sutiable memory region to reserve.
+ *
+ * So reserve park memory firstly is better, but it may cause
+ * crashkernel or quickkexec reserving failed.
+ */
+#ifdef CONFIG_ARM64_CPU_PARK
+ reserve_park_mem();
+#endif
+
reserve_crashkernel();
#ifdef CONFIG_QUICK_KEXEC
reserve_quick_kexec();
#endif
-#ifdef CONFIG_ARM64_CPU_PARK
- reserve_park_mem();
-#endif
-
reserve_pin_memory_res();
reserve_elfcorehdr();
--
2.9.5
1
0

12 Mar '21
From: ZhuLing <zhuling8(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: NA
Register pmem in arm64:
Use memmap(memmap=nn[KMG]!ss[KMG]) reserve memory and
e820(driver/nvdimm/e820.c) function to register persistent
memory in arm64. when the kernel restart or update, the data
in PMEM will not be lost and can be loaded faster. this is a
general features.
driver/nvdimm/e820.c:
The function of this file is scan "iomem_resource" and take
advantage of nvdimm resource discovery mechanism by registering
a resource named "Persistent Memory (legacy)", this function
doesn't depend on architecture.
We will push the feature to linux kernel community and discuss to
modify the file name. because people have a mistaken notion that
the e820.c is depend on x86.
If you want use this features, you need do as follows:
1.Reserve memory: add memmap to reserve memory in grub.cfg
memmap=nn[KMG]!ss[KMG] exp:memmap=100K!0x1a0000000.
2.Insmod nd_e820.ko: modprobe nd_e820.
3.Check pmem device in /dev exp: /dev/pmem0
Signed-off-by: ZhuLing <zhuling8(a)huawei.com>
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
Acked-by: Hanjun Guo <guohanjun(a)huawei.com>
---
arch/arm64/Kconfig | 21 +++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/pmem.c | 35 ++++++++++++++
arch/arm64/kernel/setup.c | 10 ++++
arch/arm64/mm/init.c | 97 ++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/Kconfig | 5 ++
drivers/nvdimm/Makefile | 2 +-
7 files changed, 170 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c451137ab..326f26d40 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -360,6 +360,27 @@ config ARM64_CPU_PARK
config ARCH_HAS_CPU_RELAX
def_bool y
+config ARM64_PMEM_RESERVE
+ bool "Reserve memory for persistent storage"
+ default n
+ help
+ Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve
+ memory for persistent storage.
+
+ Say y here to enable this feature.
+
+config ARM64_PMEM_LEGACY_DEVICE
+ bool "Create persistent storage"
+ depends on BLK_DEV
+ depends on LIBNVDIMM
+ select ARM64_PMEM_RESERVE
+ help
+ Use reserved memory for persistent storage when the kernel
+ restart or update. the data in PMEM will not be lost and
+ can be loaded faster.
+
+ Say y if unsure.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 967cb3c6d..be996f3c1 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_ARM64_MTE) += mte.o
obj-$(CONFIG_MPAM) += mpam/
+obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c
new file mode 100644
index 000000000..16eaf706f
--- /dev/null
+++ b/arch/arm64/kernel/pmem.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Derived from x86 and arm64 implement PMEM.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+static int found(struct resource *res, void *data)
+{
+ return 1;
+}
+
+static int __init register_e820_pmem(void)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+ IORESOURCE_MEM, 0, -1, NULL, found);
+ if (rc <= 0)
+ return 0;
+
+ /*
+ * See drivers/nvdimm/e820.c for the implementation, this is
+ * simply here to trigger the module to load on demand.
+ */
+ pdev = platform_device_alloc("e820_pmem", -1);
+
+ return platform_device_add(pdev);
+}
+device_initcall(register_e820_pmem);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 5e282d31a..84c71c88d 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -57,6 +57,10 @@
static int num_standard_resources;
static struct resource *standard_resources;
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+extern struct resource pmem_res;
+#endif
+
phys_addr_t __fdt_pointer __initdata;
/*
@@ -270,6 +274,12 @@ static void __init request_standard_resources(void)
request_resource(res, &pin_memory_resource);
#endif
}
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ if (pmem_res.end && pmem_res.start)
+ request_resource(&iomem_resource, &pmem_res);
+#endif
+
}
static int __init reserve_memblock_reserved_regions(void)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b3437440d..f22faea1a 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -66,6 +66,18 @@ EXPORT_SYMBOL(memstart_addr);
phys_addr_t arm64_dma_phys_limit __ro_after_init;
phys_addr_t arm64_dma32_phys_limit __ro_after_init;
+static unsigned long long pmem_size, pmem_start;
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+struct resource pmem_res = {
+ .name = "Persistent Memory (legacy)",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY
+};
+#endif
+
#ifndef CONFIG_KEXEC_CORE
static void __init reserve_crashkernel(void)
{
@@ -378,6 +390,87 @@ static int __init reserve_park_mem(void)
}
#endif
+static int __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start)
+{
+ if (!memblock_is_region_memory(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region is not memory!\n");
+ return -EINVAL;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region overlaps reserved memory!\n");
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve mem: base address is not 2MB aligned!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init parse_memmap_one(char *p)
+{
+ char *oldp;
+ phys_addr_t start_at, mem_size;
+
+ if (!p)
+ return -EINVAL;
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
+
+ if (!mem_size)
+ return -EINVAL;
+
+ mem_size = PAGE_ALIGN(mem_size);
+
+ if (*p == '!') {
+ start_at = memparse(p+1, &p);
+
+ if (is_mem_valid(mem_size, start_at) != 0)
+ return -EINVAL;
+
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ start_at, start_at + mem_size, mem_size >> 20);
+ pmem_start = start_at;
+ pmem_size = mem_size;
+ } else
+ pr_info("Unrecognized memmap option, please check the parameter.\n");
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+ while (str) {
+ char *k = strchr(str, ',');
+
+ if (k)
+ *k++ = 0;
+
+ parse_memmap_one(str);
+ str = k;
+ }
+
+ return 0;
+}
+early_param("memmap", parse_memmap_opt);
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+static void __init reserve_pmem(void)
+{
+ memblock_remove(pmem_start, pmem_size);
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ pmem_start, pmem_start + pmem_size, pmem_size >> 20);
+ pmem_res.start = pmem_start;
+ pmem_res.end = pmem_start + pmem_size - 1;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -511,6 +604,10 @@ void __init arm64_memblock_init(void)
reserve_elfcorehdr();
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ reserve_pmem();
+#endif
+
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
dma_contiguous_reserve(arm64_dma32_phys_limit);
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index b7d1eb38b..ce4de7526 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -132,3 +132,8 @@ config NVDIMM_TEST_BUILD
infrastructure.
endif
+
+config PMEM_LEGACY
+ tristate "Pmem_legacy"
+ select X86_PMEM_LEGACY if X86
+ select ARM64_PMEM_LEGACY_DEVICE if ARM64
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 29203f3d3..6f8dc9242 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
-obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_PMEM_LEGACY) += nd_e820.o
obj-$(CONFIG_OF_PMEM) += of_pmem.o
obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
--
2.19.1
1
1
raspberrypi inclusion
category: feature
bugzilla: 50432
------------------------------
This patch adjusts following arch arm related patches for
raspberry pi on non-Raspberry Pi platforms, using specific
config CONFIG_OPENEULER_RASPBERRYPI to distinguish them:
d5c13edbd8 Improve __copy_to_user and __copy_from_user performance
97145d2a6a Update vfpmodule.c
bffc462cbd Main bcm2708/bcm2709 linux port
588cfce788 cache: export clean and invalidate
41cd350cca ARM: Activate FIQs to avoid __irq_startup warnings
90607c7aaf ARM: proc-v7: Force misalignment of early stmia
ee46d0fadf reboot: Use power off rather than busy spinning when
halt is requested
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
arch/arm/include/asm/string.h | 2 ++
arch/arm/include/asm/uaccess.h | 2 ++
arch/arm/kernel/fiq.c | 4 ++++
arch/arm/kernel/reboot.c | 6 ++++++
arch/arm/lib/Makefile | 15 +++++++++++++++
arch/arm/lib/copy_from_user.S | 6 ++++++
arch/arm/lib/uaccess_with_memcpy.c | 22 +++++++++++++++++++++-
arch/arm/mm/cache-v6.S | 8 ++++++++
arch/arm/mm/cache-v7.S | 8 ++++++++
arch/arm/mm/proc-v6.S | 8 ++++++++
arch/arm/mm/proc-v7.S | 8 ++++++++
arch/arm/vfp/vfpmodule.c | 26 ++++++++++++++++++++++++++
12 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
index c22d5869e7b6..3c4ae6b3c3a6 100644
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -45,10 +45,12 @@ static inline void *memset64(uint64_t *p, uint64_t v, __kernel_size_t n)
return __memset64(p, v, n * 8, v >> 32);
}
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
#ifdef CONFIG_BCM2835_FAST_MEMCPY
#define __HAVE_ARCH_MEMCMP
extern int memcmp(const void *, const void *, size_t);
#endif
+#endif
/*
* For files that are not instrumented (e.g. mm/slub.c) we
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index f24d3fabccd6..0d8cba7a9dde 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -516,8 +516,10 @@ do { \
extern unsigned long __must_check
arm_copy_from_user(void *to, const void __user *from, unsigned long n);
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
extern unsigned long __must_check
__copy_from_user_std(void *to, const void __user *from, unsigned long n);
+#endif
static inline unsigned long __must_check
raw_copy_from_user(void *to, const void __user *from, unsigned long n)
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index c3fe7d3cf482..8116f1e52e1b 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -56,7 +56,9 @@
static unsigned long dfl_fiq_insn;
static struct pt_regs dfl_fiq_regs;
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
extern int irq_activate(struct irq_desc *desc);
+#endif
/* Default reacquire function
* - we always relinquish FIQ control
@@ -142,8 +144,10 @@ static int fiq_start;
void enable_fiq(int fiq)
{
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
struct irq_desc *desc = irq_to_desc(fiq + fiq_start);
irq_activate(desc);
+#endif
enable_irq(fiq + fiq_start);
}
diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c
index 63373adab475..ffb170568dcc 100644
--- a/arch/arm/kernel/reboot.c
+++ b/arch/arm/kernel/reboot.c
@@ -102,7 +102,13 @@ void machine_shutdown(void)
*/
void machine_halt(void)
{
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
machine_power_off();
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ local_irq_disable();
+ smp_send_stop();
+ while (1);
+#endif
}
/*
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 8271cde92dec..63820a487d4b 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -5,6 +5,7 @@
# Copyright (C) 1995-2000 Russell King
#
+ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y)
lib-y := changebit.o csumipv6.o csumpartial.o \
csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
delay.o delay-loop.o findbit.o memchr.o \
@@ -15,6 +16,18 @@ lib-y := changebit.o csumipv6.o csumpartial.o \
ucmpdi2.o lib1funcs.o div64.o \
io-readsb.o io-writesb.o io-readsl.o io-writesl.o \
call_with_stack.o bswapsdi2.o
+else
+lib-y := changebit.o csumipv6.o csumpartial.o \
+ csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
+ delay.o delay-loop.o findbit.o memchr.o memcpy.o \
+ memmove.o memset.o setbit.o \
+ strchr.o strrchr.o \
+ testchangebit.o testclearbit.o testsetbit.o \
+ ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
+ ucmpdi2.o lib1funcs.o div64.o \
+ io-readsb.o io-writesb.o io-readsl.o io-writesl.o \
+ call_with_stack.o bswapsdi2.o
+endif
mmu-y := clear_user.o copy_page.o getuser.o putuser.o \
copy_from_user.o copy_to_user.o
@@ -25,6 +38,7 @@ else
lib-y += backtrace.o
endif
+ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y)
# Choose optimised implementations for Raspberry Pi
ifeq ($(CONFIG_BCM2835_FAST_MEMCPY),y)
CFLAGS_uaccess_with_memcpy.o += -DCOPY_FROM_USER_THRESHOLD=1600
@@ -34,6 +48,7 @@ ifeq ($(CONFIG_BCM2835_FAST_MEMCPY),y)
else
lib-y += memcpy.o memmove.o memset.o
endif
+endif
# using lib_ here won't override already available weak symbols
obj-$(CONFIG_UACCESS_WITH_MEMCPY) += uaccess_with_memcpy.o
diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S
index ab7bf28dbec0..3f83d8b18b0d 100644
--- a/arch/arm/lib/copy_from_user.S
+++ b/arch/arm/lib/copy_from_user.S
@@ -107,8 +107,12 @@
.text
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENTRY(__copy_from_user_std)
WEAK(arm_copy_from_user)
+#else
+ENTRY(arm_copy_from_user)
+#endif
#ifdef CONFIG_CPU_SPECTRE
get_thread_info r3
ldr r3, [r3, #TI_ADDR_LIMIT]
@@ -118,7 +122,9 @@ WEAK(arm_copy_from_user)
#include "copy_template.S"
ENDPROC(arm_copy_from_user)
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENDPROC(__copy_from_user_std)
+#endif
.pushsection .text.fixup,"ax"
.align 0
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c
index b483e5713039..ab15ed7f599a 100644
--- a/arch/arm/lib/uaccess_with_memcpy.c
+++ b/arch/arm/lib/uaccess_with_memcpy.c
@@ -19,6 +19,7 @@
#include <asm/current.h>
#include <asm/page.h>
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
#ifndef COPY_FROM_USER_THRESHOLD
#define COPY_FROM_USER_THRESHOLD 64
#endif
@@ -26,6 +27,7 @@
#ifndef COPY_TO_USER_THRESHOLD
#define COPY_TO_USER_THRESHOLD 64
#endif
+#endif
static int
pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
@@ -51,7 +53,11 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
return 0;
pmd = pmd_offset(pud, addr);
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd)))
+#else
+ if (unlikely(pmd_none(*pmd)))
+#endif
return 0;
/*
@@ -94,6 +100,7 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
return 1;
}
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
static int
pin_page_for_read(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
{
@@ -132,8 +139,13 @@ pin_page_for_read(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
return 1;
}
+#endif
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
unsigned long noinline
+#else
+static unsigned long noinline
+#endif
__copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
{
unsigned long ua_flags;
@@ -186,6 +198,7 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
return n;
}
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
unsigned long noinline
__copy_from_user_memcpy(void *to, const void __user *from, unsigned long n)
{
@@ -236,6 +249,7 @@ __copy_from_user_memcpy(void *to, const void __user *from, unsigned long n)
out:
return n;
}
+#endif
unsigned long
arm_copy_to_user(void __user *to, const void *from, unsigned long n)
@@ -247,7 +261,11 @@ arm_copy_to_user(void __user *to, const void *from, unsigned long n)
* With frame pointer disabled, tail call optimization kicks in
* as well making this test almost invisible.
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
if (n < COPY_TO_USER_THRESHOLD) {
+#else
+ if (n < 64) {
+#endif
unsigned long ua_flags = uaccess_save_and_enable();
n = __copy_to_user_std(to, from, n);
uaccess_restore(ua_flags);
@@ -258,6 +276,7 @@ arm_copy_to_user(void __user *to, const void *from, unsigned long n)
return n;
}
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
unsigned long __must_check
arm_copy_from_user(void *to, const void __user *from, unsigned long n)
{
@@ -283,7 +302,8 @@ arm_copy_from_user(void *to, const void __user *from, unsigned long n)
#endif
return n;
}
-
+#endif
+
static unsigned long noinline
__clear_user_memset(void __user *addr, unsigned long n)
{
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 868011801521..614d4ff2a760 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -198,7 +198,11 @@ ENTRY(v6_flush_kern_dcache_area)
* - start - virtual start address of region
* - end - virtual end address of region
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENTRY(v6_dma_inv_range)
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+v6_dma_inv_range:
+#endif
#ifdef CONFIG_DMA_CACHE_RWFO
ldrb r2, [r0] @ read for ownership
strb r2, [r0] @ write for ownership
@@ -243,7 +247,11 @@ ENTRY(v6_dma_inv_range)
* - start - virtual start address of region
* - end - virtual end address of region
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENTRY(v6_dma_clean_range)
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+v6_dma_clean_range:
+#endif
bic r0, r0, #D_CACHE_LINE_SIZE - 1
1:
#ifdef CONFIG_DMA_CACHE_RWFO
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 536df5db66e4..58df59734e40 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -363,8 +363,12 @@ ENDPROC(v7_flush_kern_dcache_area)
* - start - virtual start address of region
* - end - virtual end address of region
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENTRY(b15_dma_inv_range)
ENTRY(v7_dma_inv_range)
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+v7_dma_inv_range:
+#endif
dcache_line_size r2, r3
sub r3, r2, #1
tst r0, r3
@@ -394,8 +398,12 @@ ENDPROC(v7_dma_inv_range)
* - start - virtual start address of region
* - end - virtual end address of region
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
ENTRY(b15_dma_clean_range)
ENTRY(v7_dma_clean_range)
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+v7_dma_clean_range:
+#endif
dcache_line_size r2, r3
sub r3, r2, #1
bic r0, r0, r3
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index b3a2fce22eac..b651eaa1ee40 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -71,6 +71,7 @@ ENDPROC(cpu_v6_reset)
* IRQs are already disabled.
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* See jira SW-5991 for details of this workaround */
ENTRY(cpu_v6_do_idle)
.align 5
@@ -84,6 +85,13 @@ ENTRY(cpu_v6_do_idle)
nop
bne 1b
ret lr
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ENTRY(cpu_v6_do_idle)
+ mov r1, #0
+ mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode
+ mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt
+ ret lr
+#endif
ENTRY(cpu_v6_dcache_clean_area)
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 3e77e8982df3..ef0e00249515 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -287,8 +287,10 @@ __v7_ca17mp_setup:
mov r10, #0
1: adr r0, __v7_setup_stack_ptr
ldr r12, [r0]
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
tst r12, #0x1f
addeq r12, r12, #4
+#endif
add r12, r12, r0 @ the local stack
stmia r12, {r1-r6, lr} @ v7_invalidate_l1 touches r0-r6
bl v7_invalidate_l1
@@ -476,8 +478,10 @@ __v7_setup:
adr r0, __v7_setup_stack_ptr
ldr r12, [r0]
add r12, r12, r0 @ the local stack
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
tst r12, #0x1f
addeq r12, r12, #4
+#endif
stmia r12, {r1-r6, lr} @ v7_invalidate_l1 touches r0-r6
bl v7_invalidate_l1
ldmia r12, {r1-r6, lr}
@@ -561,7 +565,11 @@ ENDPROC(__v7_setup)
.bss
.align 2
__v7_setup_stack:
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
.space 4 * 8 @ 7 registers + 1 spare
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ .space 4 * 7 @ 7 registers
+#endif
__INITDATA
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 1e2dcf81aefa..f7238e00db7c 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -176,11 +176,16 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
* case the thread migrates to a different CPU. The
* restoring is done lazily.
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) {
/* vfp_save_state oopses on VFP11 if EX bit set */
fmxr(FPEXC, fpexc & ~FPEXC_EX);
vfp_save_state(vfp_current_hw_state[cpu], fpexc);
}
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu])
+ vfp_save_state(vfp_current_hw_state[cpu], fpexc);
+#endif
#endif
/*
@@ -457,16 +462,22 @@ static int vfp_pm_suspend(void)
/* if vfp is on, then save state for resumption */
if (fpexc & FPEXC_EN) {
pr_debug("%s: saving vfp state\n", __func__);
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* vfp_save_state oopses on VFP11 if EX bit set */
fmxr(FPEXC, fpexc & ~FPEXC_EX);
+#endif
vfp_save_state(&ti->vfpstate, fpexc);
/* disable, just in case */
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
} else if (vfp_current_hw_state[ti->cpu]) {
#ifndef CONFIG_SMP
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* vfp_save_state oopses on VFP11 if EX bit set */
fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN);
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ fmxr(FPEXC, fpexc | FPEXC_EN);
+#endif
vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc);
fmxr(FPEXC, fpexc);
#endif
@@ -529,8 +540,12 @@ void vfp_sync_hwstate(struct thread_info *thread)
/*
* Save the last VFP state on this CPU.
*/
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* vfp_save_state oopses on VFP11 if EX bit set */
fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN);
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ fmxr(FPEXC, fpexc | FPEXC_EN);
+#endif
vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN);
fmxr(FPEXC, fpexc);
}
@@ -596,7 +611,9 @@ int vfp_restore_user_hwstate(struct user_vfp *ufp, struct user_vfp_exc *ufp_exc)
struct thread_info *thread = current_thread_info();
struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
unsigned long fpexc;
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
u32 fpsid = fmrx(FPSID);
+#endif
/* Disable VFP to avoid corrupting the new thread state. */
vfp_flush_hwstate(thread);
@@ -619,11 +636,16 @@ int vfp_restore_user_hwstate(struct user_vfp *ufp, struct user_vfp_exc *ufp_exc)
/* Ensure the VFP is enabled. */
fpexc |= FPEXC_EN;
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* Mask FPXEC_EX and FPEXC_FP2V if not required by VFP arch */
if ((fpsid & FPSID_ARCH_MASK) != (1 << FPSID_ARCH_BIT)) {
/* Ensure FPINST2 is invalid and the exception flag is cleared. */
fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
}
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ /* Ensure FPINST2 is invalid and the exception flag is cleared. */
+ fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
+#endif
hwstate->fpexc = fpexc;
@@ -738,8 +760,12 @@ void kernel_neon_begin(void)
cpu = get_cpu();
fpexc = fmrx(FPEXC) | FPEXC_EN;
+#ifdef CONFIG_OPENEULER_RASPBERRYPI
/* vfp_save_state oopses on VFP11 if EX bit set */
fmxr(FPEXC, fpexc & ~FPEXC_EX);
+#else /* !CONFIG_OPENEULER_RASPBERRYPI */
+ fmxr(FPEXC, fpexc);
+#endif
/*
* Save the userland NEON/VFP state. Under UP,
--
2.20.1
2
1

[PATCH openEuler-1.0-LTS] sysctl: control if check validity of freelist and connector debug by sysctl
by Cheng Jian 11 Mar '21
by Cheng Jian 11 Mar '21
11 Mar '21
From: Yang Yingliang <yangyingliang(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 47452
CVE: NA
-------------------------------------------------
Change control methods of check validity of freelist and
connector debug to sysctl.
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Cheng Jian <cj.chengjian(a)huawei.com>
---
drivers/connector/connector.c | 1 +
include/linux/slab.h | 4 ---
kernel/sysctl.c | 20 +++++++++++
mm/slub.c | 63 ++++++++++++++---------------------
4 files changed, 46 insertions(+), 42 deletions(-)
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index a8df9ecbf42b..b5cdd0b99736 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -42,6 +42,7 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_CONNECTOR);
static struct cn_dev cdev;
static int cn_already_initialized;
+int sysctl_connector_debug = 0;
/*
* Sends mult (multiple) cn_msg at a time.
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 1ab5fd97dec8..d6393413ef09 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -24,8 +24,6 @@
*/
/* DEBUG: Perform (expensive) checks on alloc/free */
#define SLAB_CONSISTENCY_CHECKS ((slab_flags_t __force)0x00000100U)
-/* Check if freelist is valid */
-#define SLAB_NO_FREELIST_CHECKS ((slab_flags_t __force)0x00000200U)
/* DEBUG: Red zone objs in a cache */
#define SLAB_RED_ZONE ((slab_flags_t __force)0x00000400U)
/* DEBUG: Poison objects */
@@ -113,8 +111,6 @@
#define SLAB_KASAN 0
#endif
-#define SLAB_CONNECTOR_DEBUG ((slab_flags_t __force)0x10000000U)
-
/* The following flags affect the page allocator grouping pages by mobility */
/* Objects are reclaimable */
#define SLAB_RECLAIM_ACCOUNT ((slab_flags_t __force)0x00020000U)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 665c9e2a8802..c921ee10615a 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1245,6 +1245,7 @@ static struct ctl_table kern_table[] = {
{ }
};
+extern int sysctl_isolate_corrupted_freelist;
static struct ctl_table vm_table[] = {
{
.procname = "overcommit_memory",
@@ -1714,6 +1715,15 @@ static struct ctl_table vm_table[] = {
.extra2 = (void *)&mmap_rnd_compat_bits_max,
},
#endif
+ {
+ .procname = "isolate_corrupted_freelist",
+ .data = &sysctl_isolate_corrupted_freelist,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
{ }
};
@@ -1925,6 +1935,7 @@ static struct ctl_table fs_table[] = {
{ }
};
+extern int sysctl_connector_debug;
static struct ctl_table debug_table[] = {
#ifdef CONFIG_SYSCTL_EXCEPTION_TRACE
{
@@ -1946,6 +1957,15 @@ static struct ctl_table debug_table[] = {
.extra2 = &one,
},
#endif
+ {
+ .procname = "connector-debug",
+ .data = &sysctl_connector_debug,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
{ }
};
diff --git a/mm/slub.c b/mm/slub.c
index ee0d18699bde..2301c04353d0 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1221,30 +1221,6 @@ static noinline int free_debug_processing(
return ret;
}
-/*
- * Check if the next object in freechain is
- * valid, then isolate the corrupted freelist.
- */
-int isolate_cnt = 0;
-static bool isolate_corrupted_freelist(struct kmem_cache *s, struct page *page,
- void **freelist, void *next)
-{
- if (!(slub_debug & SLAB_NO_FREELIST_CHECKS) &&
- (!check_valid_pointer(s, page, next))) {
- /* Need caller make sure freelist is not NULL */
- *freelist = NULL;
- isolate_cnt++;
-
- slab_fix(s, "Freelist corrupt,isolate corrupted freechain.");
- pr_info("freelist=%lx object=%lx, page->base=%lx, page->objects=%u, objsize=%u, s->offset=%d page:%llx\n",
- (long)freelist, (long)next, (long)page_address(page), page->objects, s->size, s->offset, (u64)page);
-
- return true;
- }
-
- return false;
-}
-
static int __init setup_slub_debug(char *str)
{
slub_debug = DEBUG_DEFAULT_FLAGS;
@@ -1291,14 +1267,6 @@ static int __init setup_slub_debug(char *str)
case 'a':
slub_debug |= SLAB_FAILSLAB;
break;
- case 'n':
- slub_debug |= SLAB_NO_FREELIST_CHECKS;
- pr_info("Freelist pointer check disabled.");
- break;
- case 'd':
- slub_debug |= SLAB_CONNECTOR_DEBUG;
- pr_info("Connector debug enabled.\n");
- break;
case 'o':
/*
* Avoid enabling debugging on caches if its minimum
@@ -1311,8 +1279,6 @@ static int __init setup_slub_debug(char *str)
*str);
}
}
- if (!(slub_debug & SLAB_NO_FREELIST_CHECKS))
- pr_info("Freelist pointer check enabled.");
check_slabs:
if (*str == ',')
@@ -1380,12 +1346,33 @@ static bool freelist_corrupted(struct kmem_cache *s, struct page *page,
{
return false;
}
+#endif /* CONFIG_SLUB_DEBUG */
+
+extern int sysctl_connector_debug;
+/*
+ * Check if the next object in freechain is
+ * valid, then isolate the corrupted freelist.
+ */
+int isolate_cnt = 0;
+int sysctl_isolate_corrupted_freelist = 1;
static bool isolate_corrupted_freelist(struct kmem_cache *s, struct page *page,
- void **freelist, void *nextfree)
+ void **freelist, void *next)
{
+ if (sysctl_isolate_corrupted_freelist &&
+ (!check_valid_pointer(s, page, next))) {
+ /* Need caller make sure freelist is not NULL */
+ *freelist = NULL;
+ isolate_cnt++;
+
+ slab_fix(s, "Freelist corrupt,isolate corrupted freechain.");
+ pr_info("freelist=%lx object=%lx, page->base=%lx, page->objects=%u, objsize=%u, s->offset=%d page:%llx\n",
+ (long)freelist, (long)next, (long)page_address(page), page->objects, s->size, s->offset, (u64)page);
+
+ return true;
+ }
+
return false;
}
-#endif /* CONFIG_SLUB_DEBUG */
/*
* Hooks for other subsystems that check memory allocations. In a typical
@@ -2798,7 +2785,7 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
if (unlikely(gfpflags & __GFP_ZERO) && object)
memset(object, 0, s->object_size);
- if ((slub_debug & SLAB_CONNECTOR_DEBUG) &&
+ if (sysctl_connector_debug &&
unlikely(gfpflags & __GFP_CONNECTOR) && object) {
if (s->object_size == 512)
memset(object + 504, 0xad, 8);
@@ -4015,7 +4002,7 @@ void kfree(const void *x)
__free_pages(page, compound_order(page));
return;
}
- if ((slub_debug & SLAB_CONNECTOR_DEBUG) &&
+ if (sysctl_connector_debug &&
unlikely(page->slab_cache->object_size == 512)) {
u64 *tail = (u64 *)(x + 504);
--
2.25.1
1
0
bugfix for 20.03 at 202102
Alexey Gladkov (1):
moduleparam: Save information about built-in modules in separate file
Amir Goldstein (1):
ovl: skip getxattr of security labels
Aurelien Aptel (1):
cifs: report error instead of invalid when revalidating a dentry fails
Baptiste Lepers (1):
udp: Prevent reuseport_select_sock from reading uninitialized socks
Byron Stanoszek (1):
tmpfs: restore functionality of nr_inodes=0
Chris Down (2):
tmpfs: per-superblock i_ino support
tmpfs: support 64-bit inums per-sb
Christian Brauner (1):
sysctl: handle overflow in proc_get_long
Cong Wang (1):
af_key: relax availability checks for skb size calculation
Dave Wysochanski (2):
SUNRPC: Move simple_get_bytes and simple_get_netobj into private
header
SUNRPC: Handle 0 length opaque XDR object data properly
Dong Kai (1):
livepatch/core: Fix jump_label_apply_nops called multi times
Edwin Peer (1):
net: watchdog: hold device global xmit lock during tx disable
Eric Biggers (1):
fs: fix lazytime expiration handling in __writeback_single_inode()
Eric Dumazet (1):
net_sched: gen_estimator: support large ewma log
Eyal Birger (1):
xfrm: fix disable_xfrm sysctl when used on xfrm interfaces
Florian Westphal (1):
netfilter: conntrack: skip identical origin tuple in same zone only
Gaurav Kohli (1):
tracing: Fix race in trace_open and buffer resize call
Gustavo A. R. Silva (1):
smb3: Fix out-of-bounds bug in SMB2_negotiate()
Hugh Dickins (1):
mm: thp: fix MADV_REMOVE deadlock on shmem THP
Jakub Kicinski (1):
net: sit: unregister_netdevice on newlink's error path
Jan Kara (1):
writeback: Drop I_DIRTY_TIME_EXPIRE
Jozsef Kadlecsik (1):
netfilter: xt_recent: Fix attempt to update deleted entry
Liangyan (1):
ovl: fix dentry leak in ovl_get_redirect
Lin Feng (1):
bfq-iosched: Revert "bfq: Fix computation of shallow depth"
Marc Zyngier (1):
genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is
set
Martin K. Petersen (2):
scsi: sd: block: Fix regressions in read-only block device handling
scsi: sd: block: Fix kabi change by 'scsi: sd: block: Fix regressions
in read-only block device handling'
Martin Willi (1):
vrf: Fix fast path output packet handling with async Netfilter rules
Masami Hiramatsu (1):
tracing/kprobe: Fix to support kretprobe events on unloaded modules
Miklos Szeredi (4):
proc/mounts: add cursor
ovl: perform vfs_getxattr() with mounter creds
cap: fix conversions on getxattr
ovl: expand warning in ovl_d_real()
Mikulas Patocka (1):
dm integrity: conditionally disable "recalculate" feature
Ming Lei (4):
scsi: core: Run queue in case of I/O resource contention failure
scsi: core: Only re-run queue in scsi_end_request() if device queue is
busy
block: don't hold q->sysfs_lock in elevator_init_mq
blk-mq: don't hold q->sysfs_lock in blk_mq_map_swqueue
Muchun Song (4):
mm: hugetlbfs: fix cannot migrate the fallocated HugeTLB page
mm: hugetlb: fix a race between freeing and dissolving the page
mm: hugetlb: fix a race between isolating and freeing page
mm: hugetlb: remove VM_BUG_ON_PAGE from page_huge_active
NeilBrown (1):
net: fix iteration for sctp transport seq_files
Ondrej Jirman (1):
brcmfmac: Loading the correct firmware for brcm43456
Pablo Neira Ayuso (1):
netfilter: nft_dynset: add timeout extension to template
Pavel Begunkov (1):
list: introduce list_for_each_continue()
Pengcheng Yang (1):
tcp: fix TLP timer not set when CA_STATE changes from DISORDER to OPEN
Peter Zijlstra (2):
kthread: Extract KTHREAD_IS_PER_CPU
workqueue: Restrict affinity change to rescuer
Roi Dayan (1):
net/mlx5: Fix memory leak on flow table creation error flow
Roman Gushchin (1):
memblock: do not start bottom-up allocations with kernel_end
Sabyrzhan Tasbolatov (1):
net/rds: restrict iovecs length for RDS_CMSG_RDMA_ARGS
Shmulik Ladkani (1):
xfrm: Fix oops in xfrm_replay_advance_bmp
Steven Rostedt (VMware) (3):
fgraph: Initialize tracing_graph_pause at task creation
tracing: Do not count ftrace events in top level enable output
tracing: Check length before giving out the filter buffer
Sven Auhagen (1):
netfilter: flowtable: fix tcp and udp header checksum update
Vadim Fedorenko (1):
net: ip_tunnel: fix mtu calculation
Wang Hai (1):
Revert "mm/slub: fix a memory leak in sysfs_slab_add()"
Wang ShaoBo (1):
kretprobe: Avoid re-registration of the same kretprobe earlier
Willem de Bruijn (1):
esp: avoid unneeded kmap_atomic call
Xiao Ni (1):
md: Set prev_flush_start and flush_bio in an atomic way
Yang Yingliang (3):
sysctl/mm: fix compile error when CONFIG_SLUB is disabled
config: disable config TMPFS_INODE64 by default
connector: change GFP_CONNECTOR to bit-31
Ye Bin (3):
scsi: sd: block: Fix read-only flag residuals when partition table
change
Revert "scsi: sd: block: Fix read-only flag residuals when partition
table change"
Revert "scsi: sg: fix memory leak in sg_build_indirect"
Yonglong Liu (4):
net: hns3: adds support for setting pf max tx rate via sysfs
net: hns3: update hns3 version to 1.9.38.10
net: hns3: fix 'ret' may be used uninitialized problem
net: hns3: update hns3 version to 1.9.38.11
Yufen Yu (1):
scsi: fix kabi for scsi_device
Zhang Xiaoxu (1):
proc/mounts: Fix kabi broken
liubo (3):
etmem: add etmem-scan feature
etmem: add etmem-swap feature
config: Enable the config option of the etmem feature
shiyongbang (3):
gpu: hibmc: Fix erratic display during startup stage.
gpu: hibmc: Use drm get pci dev api.
gpu: hibmc: Fix stuck when switch GUI to text.
zhangyi (F) (1):
ext4: find old entry again if failed to rename whiteout
.gitignore | 1 +
Documentation/device-mapper/dm-integrity.txt | 7 +
Documentation/dontdiff | 1 +
Documentation/filesystems/tmpfs.txt | 17 +
Documentation/kbuild/kbuild.txt | 5 +
Makefile | 2 +
arch/arm64/configs/hulk_defconfig | 3 +
arch/arm64/configs/openeuler_defconfig | 2 +
arch/x86/configs/hulk_defconfig | 2 +
arch/x86/configs/openeuler_defconfig | 2 +
block/bfq-iosched.c | 8 +-
block/blk-mq.c | 7 -
block/elevator.c | 14 +-
block/genhd.c | 33 +-
block/ioctl.c | 4 +
block/partition-generic.c | 7 +-
drivers/connector/connector.c | 6 +-
.../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 68 +-
.../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 2 +
.../gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 1 +
drivers/md/dm-integrity.c | 24 +-
drivers/md/md.c | 2 +
drivers/net/ethernet/hisilicon/hns3/Makefile | 3 +-
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 10 +-
.../hns3/hns3_cae/hns3_cae_version.h | 2 +-
.../net/ethernet/hisilicon/hns3/hns3_enet.h | 2 +-
.../hns3_extension/hns3pf/hclge_main_it.c | 33 +
.../hns3/hns3_extension/hns3pf/hclge_sysfs.c | 140 +++
.../hns3/hns3_extension/hns3pf/hclge_sysfs.h | 14 +
.../hisilicon/hns3/hns3pf/hclge_main.c | 17 +
.../hisilicon/hns3/hns3pf/hclge_main.h | 7 +-
.../hisilicon/hns3/hns3vf/hclgevf_main.h | 2 +-
.../net/ethernet/mellanox/mlx5/core/fs_core.c | 1 +
drivers/net/vrf.c | 92 +-
.../broadcom/brcm80211/brcmfmac/sdio.c | 4 +-
drivers/scsi/scsi_lib.c | 59 +-
drivers/scsi/sg.c | 6 +-
fs/Kconfig | 21 +
fs/cifs/dir.c | 22 +-
fs/cifs/smb2pdu.h | 2 +-
fs/ext4/inode.c | 2 +-
fs/ext4/namei.c | 29 +-
fs/fs-writeback.c | 36 +-
fs/hugetlbfs/inode.c | 3 +-
fs/mount.h | 17 +-
fs/namespace.c | 119 +-
fs/overlayfs/copy_up.c | 15 +-
fs/overlayfs/dir.c | 2 +-
fs/overlayfs/inode.c | 2 +
fs/overlayfs/super.c | 13 +-
fs/proc/Makefile | 2 +
fs/proc/base.c | 4 +
fs/proc/etmem_scan.c | 1046 +++++++++++++++++
fs/proc/etmem_scan.h | 132 +++
fs/proc/etmem_swap.c | 102 ++
fs/proc/internal.h | 2 +
fs/proc/task_mmu.c | 117 ++
fs/proc_namespace.c | 4 +-
fs/xfs/xfs_trans_inode.c | 4 +-
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/fs.h | 16 +-
include/linux/genhd.h | 5 +
include/linux/gfp.h | 8 +-
include/linux/hugetlb.h | 3 +
include/linux/kprobes.h | 2 +-
include/linux/kthread.h | 3 +
include/linux/list.h | 10 +
include/linux/mm_types.h | 18 +
include/linux/module.h | 1 +
include/linux/moduleparam.h | 12 +-
include/linux/mount.h | 4 +-
include/linux/msi.h | 6 +
include/linux/netdevice.h | 2 +
include/linux/shmem_fs.h | 3 +
include/linux/sunrpc/xdr.h | 3 +-
include/linux/swap.h | 5 +
include/net/tcp.h | 2 +-
include/scsi/scsi_device.h | 3 +-
include/trace/events/writeback.h | 1 -
init/init_task.c | 3 +-
kernel/irq/msi.c | 44 +-
kernel/kprobes.c | 36 +-
kernel/kthread.c | 27 +-
kernel/livepatch/core.c | 20 +-
kernel/smpboot.c | 1 +
kernel/sysctl.c | 6 +
kernel/trace/ftrace.c | 2 -
kernel/trace/ring_buffer.c | 4 +
kernel/trace/trace.c | 2 +-
kernel/trace/trace_events.c | 3 +-
kernel/trace/trace_kprobe.c | 4 +-
kernel/workqueue.c | 9 +-
lib/Kconfig | 11 +
mm/huge_memory.c | 37 +-
mm/hugetlb.c | 48 +-
mm/memblock.c | 49 +-
mm/pagewalk.c | 1 +
mm/shmem.c | 133 ++-
mm/slub.c | 14 +-
mm/vmscan.c | 112 ++
mm/vmstat.c | 4 +
net/core/gen_estimator.c | 11 +-
net/core/sock_reuseport.c | 2 +-
net/ipv4/esp4.c | 7 +-
net/ipv4/ip_tunnel.c | 16 +-
net/ipv4/tcp_input.c | 10 +-
net/ipv4/tcp_recovery.c | 5 +-
net/ipv6/esp6.c | 7 +-
net/ipv6/sit.c | 5 +-
net/key/af_key.c | 6 +-
net/netfilter/nf_conntrack_core.c | 3 +-
net/netfilter/nf_flow_table_core.c | 4 +-
net/netfilter/nft_dynset.c | 4 +-
net/netfilter/xt_recent.c | 12 +-
net/rds/rdma.c | 3 +
net/sctp/proc.c | 16 +-
net/sunrpc/auth_gss/auth_gss.c | 30 +-
net/sunrpc/auth_gss/auth_gss_internal.h | 45 +
net/sunrpc/auth_gss/gss_krb5_mech.c | 31 +-
net/xfrm/xfrm_input.c | 2 +-
net/xfrm/xfrm_policy.c | 4 +-
scripts/link-vmlinux.sh | 3 +
security/commoncap.c | 67 +-
virt/kvm/kvm_main.c | 6 +
124 files changed, 2817 insertions(+), 466 deletions(-)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.c
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.h
create mode 100644 fs/proc/etmem_scan.c
create mode 100644 fs/proc/etmem_scan.h
create mode 100644 fs/proc/etmem_swap.c
create mode 100644 net/sunrpc/auth_gss/auth_gss_internal.h
--
2.25.1
1
82
From: Pavel Begunkov <asml.silence(a)gmail.com>
mainline inclusion
from mainline-v5.6-rc1
commit 28ca0d6d39ab1d01c86762c82a585b7cedd2920c
category: bugfix
bugzilla: 35619
CVE: NA
--------------------------------
As other *continue() helpers, this continues iteration from a given
position.
Signed-off-by: Pavel Begunkov <asml.silence(a)gmail.com>
Signed-off-by: Jens Axboe <axboe(a)kernel.dk>
Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5(a)huawei.com>
Reviewed-by: zhangyi (F) <yi.zhang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/list.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/include/linux/list.h b/include/linux/list.h
index de04cc5ed536..0e540581d52c 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -455,6 +455,16 @@ static inline void list_splice_tail_init(struct list_head *list,
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
+/**
+ * list_for_each_continue - continue iteration over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ *
+ * Continue to iterate over a list, continuing after the current position.
+ */
+#define list_for_each_continue(pos, head) \
+ for (pos = pos->next; pos != (head); pos = pos->next)
+
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
--
2.25.1
1
11

[PATCH openEuler-21.03 v1] park: Reserve park mem before kexec reserved
by sangyan@huawei.com 10 Mar '21
by sangyan@huawei.com 10 Mar '21
10 Mar '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
------------------------------
reserve_crashkernel or reserve_quick_kexec may find one sutiable
memory region and reserves it, which address of the region is
not fixed.
As a result, cpu park reserves memory could be failed while
specified address used by crashkernel or quickkexec.
So, move reserve_park_mem before reserve_crashkernel and
reserve_quick_kexec.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/arm64/mm/init.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b343744..043a981 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -497,16 +497,16 @@ void __init arm64_memblock_init(void)
else
arm64_dma32_phys_limit = PHYS_MASK + 1;
+#ifdef CONFIG_ARM64_CPU_PARK
+ reserve_park_mem();
+#endif
+
reserve_crashkernel();
#ifdef CONFIG_QUICK_KEXEC
reserve_quick_kexec();
#endif
-#ifdef CONFIG_ARM64_CPU_PARK
- reserve_park_mem();
-#endif
-
reserve_pin_memory_res();
reserve_elfcorehdr();
--
2.9.5
1
0

10 Mar '21
From: ZhuLing <zhuling8(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: NA
Register pmem in arm64:
Use memmap(memmap=nn[KMG]!ss[KMG]) reserve memory and
e820(driver/nvdimm/e820.c) function to register persistent
memory in arm64. when the kernel restart or update, the data
in PMEM will not be lost and can be loaded faster. this is a
general features.
driver/nvdimm/e820.c:
The function of this file is scan "iomem_resource" and take
advantage of nvdimm resource discovery mechanism by registering
a resource named "Persistent Memory (legacy)", this function
doesn't depend on architecture.
We will push the feature to linux kernel community and discuss to
modify the file name. because people have a mistaken notion that
the e820.c is depend on x86.
If you want use this features, you need do as follows:
1.Reserve memory: add memmap to reserve memory in grub.cfg
memmap=nn[KMG]!ss[KMG] exp:memmap=100K!0x1a0000000.
2.Insmod nd_e820.ko: modprobe nd_e820.
3.Check pmem device in /dev exp: /dev/pmem0
Signed-off-by: ZhuLing <zhuling8(a)huawei.com>
---
arch/arm64/Kconfig | 21 +++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/pmem.c | 35 ++++++++++++++
arch/arm64/kernel/setup.c | 10 ++++
arch/arm64/mm/init.c | 97 ++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/Kconfig | 5 ++
drivers/nvdimm/Makefile | 2 +-
7 files changed, 170 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c451137ab..326f26d40 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -360,6 +360,27 @@ config ARM64_CPU_PARK
config ARCH_HAS_CPU_RELAX
def_bool y
+config ARM64_PMEM_RESERVE
+ bool "Reserve memory for persistent storage"
+ default n
+ help
+ Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve
+ memory for persistent storage.
+
+ Say y here to enable this feature.
+
+config ARM64_PMEM_LEGACY_DEVICE
+ bool "Create persistent storage"
+ depends on BLK_DEV
+ depends on LIBNVDIMM
+ select ARM64_PMEM_RESERVE
+ help
+ Use reserved memory for persistent storage when the kernel
+ restart or update. the data in PMEM will not be lost and
+ can be loaded faster.
+
+ Say y if unsure.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 967cb3c6d..be996f3c1 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_ARM64_MTE) += mte.o
obj-$(CONFIG_MPAM) += mpam/
+obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c
new file mode 100644
index 000000000..16eaf706f
--- /dev/null
+++ b/arch/arm64/kernel/pmem.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Derived from x86 and arm64 implement PMEM.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+static int found(struct resource *res, void *data)
+{
+ return 1;
+}
+
+static int __init register_e820_pmem(void)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+ IORESOURCE_MEM, 0, -1, NULL, found);
+ if (rc <= 0)
+ return 0;
+
+ /*
+ * See drivers/nvdimm/e820.c for the implementation, this is
+ * simply here to trigger the module to load on demand.
+ */
+ pdev = platform_device_alloc("e820_pmem", -1);
+
+ return platform_device_add(pdev);
+}
+device_initcall(register_e820_pmem);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 5e282d31a..84c71c88d 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -57,6 +57,10 @@
static int num_standard_resources;
static struct resource *standard_resources;
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+extern struct resource pmem_res;
+#endif
+
phys_addr_t __fdt_pointer __initdata;
/*
@@ -270,6 +274,12 @@ static void __init request_standard_resources(void)
request_resource(res, &pin_memory_resource);
#endif
}
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ if (pmem_res.end && pmem_res.start)
+ request_resource(&iomem_resource, &pmem_res);
+#endif
+
}
static int __init reserve_memblock_reserved_regions(void)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b3437440d..f22faea1a 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -66,6 +66,18 @@ EXPORT_SYMBOL(memstart_addr);
phys_addr_t arm64_dma_phys_limit __ro_after_init;
phys_addr_t arm64_dma32_phys_limit __ro_after_init;
+static unsigned long long pmem_size, pmem_start;
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+struct resource pmem_res = {
+ .name = "Persistent Memory (legacy)",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY
+};
+#endif
+
#ifndef CONFIG_KEXEC_CORE
static void __init reserve_crashkernel(void)
{
@@ -378,6 +390,87 @@ static int __init reserve_park_mem(void)
}
#endif
+static int __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start)
+{
+ if (!memblock_is_region_memory(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region is not memory!\n");
+ return -EINVAL;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region overlaps reserved memory!\n");
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve mem: base address is not 2MB aligned!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init parse_memmap_one(char *p)
+{
+ char *oldp;
+ phys_addr_t start_at, mem_size;
+
+ if (!p)
+ return -EINVAL;
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
+
+ if (!mem_size)
+ return -EINVAL;
+
+ mem_size = PAGE_ALIGN(mem_size);
+
+ if (*p == '!') {
+ start_at = memparse(p+1, &p);
+
+ if (is_mem_valid(mem_size, start_at) != 0)
+ return -EINVAL;
+
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ start_at, start_at + mem_size, mem_size >> 20);
+ pmem_start = start_at;
+ pmem_size = mem_size;
+ } else
+ pr_info("Unrecognized memmap option, please check the parameter.\n");
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+ while (str) {
+ char *k = strchr(str, ',');
+
+ if (k)
+ *k++ = 0;
+
+ parse_memmap_one(str);
+ str = k;
+ }
+
+ return 0;
+}
+early_param("memmap", parse_memmap_opt);
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+static void __init reserve_pmem(void)
+{
+ memblock_remove(pmem_start, pmem_size);
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ pmem_start, pmem_start + pmem_size, pmem_size >> 20);
+ pmem_res.start = pmem_start;
+ pmem_res.end = pmem_start + pmem_size - 1;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -511,6 +604,10 @@ void __init arm64_memblock_init(void)
reserve_elfcorehdr();
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ reserve_pmem();
+#endif
+
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
dma_contiguous_reserve(arm64_dma32_phys_limit);
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index b7d1eb38b..ce4de7526 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -132,3 +132,8 @@ config NVDIMM_TEST_BUILD
infrastructure.
endif
+
+config PMEM_LEGACY
+ tristate "Pmem_legacy"
+ select X86_PMEM_LEGACY if X86
+ select ARM64_PMEM_LEGACY_DEVICE if ARM64
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 29203f3d3..6f8dc9242 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
-obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_PMEM_LEGACY) += nd_e820.o
obj-$(CONFIG_OF_PMEM) += of_pmem.o
obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
--
2.19.1
1
1
ok!
1
0
4
7
From: Fang Yafen <yafen(a)iscas.ac.cn>
Fix the following compile error when using bcm2711_defconfig (for RPi).
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `set -e;
echo ' DTCO arch/arm64/boot/dts/overlays/act-led.dtbo';
mkdir -p arch/arm64/boot/dts/overlays/ ;
gcc -E -Wp,-MMD,arch/arm64/boot/dts/overlays/.act-led.dtbo.d.pre.tmp
-nostdinc -I./scripts/dtc/include-prefixes -undef -D__DTS__
-x assembler-with-cpp
-o arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp
arch/arm64/boot/dts/overlays/act-led-overlay.dts ;
./scripts/dtc/dtc -@ -H epapr -O dtb
-o arch/arm64/boot/dts/overlays/act-led.dtbo -b 0
-i arch/arm64/boot/dts/overlays/ -Wno-interrupt_provider
-Wno-unit_address_vs_reg -Wno-unit_address_format -Wno-gpios_property
-Wno-avoid_unnecessary_addr_size -Wno-alias_paths
-Wno-graph_child_address -Wno-simple_bus_reg
-Wno-unique_unit_address -Wno-pci_device_reg
-Wno-interrupts_property ifeq (y,y) -Wno-label_is_string
-Wno-reg_format -Wno-pci_device_bus_num -Wno-i2c_bus_reg
-Wno-spi_bus_reg -Wno-avoid_default_addr_size endif
-d arch/arm64/boot/dts/overlays/.act-led.dtbo.d.dtc.tmp
arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp ;
cat ...; rm -f arch/arm64/boot/dts/overlays/.act-led.dtbo.d'
make[2]: *** [scripts/Makefile.lib;363:
arch/arm64/boot/dts/overlays/act-led.dtbo] Error 1
make[2]: *** Waiting for unfinished jobs....
Related patches:
ffa2d13ccc3 BCM2708: Add core Device Tree support
4894352ec98 kbuild: Silence unavoidable dtc overlay warnings
a4a4d07f0cf kbuild: keep the original function for non-RPi
Signed-off-by: Fang Yafen <yafen(a)iscas.ac.cn>
---
scripts/Makefile.lib | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index c23e3ae7ef40..a0e0e2543165 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -342,25 +342,25 @@ endef
$(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
$(call if_changed_rule,dtc,yaml)
+ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y)
quiet_cmd_dtco = DTCO $@
cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; \
$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
$(DTC) -@ -H epapr -O dtb -o $@ -b 0 \
-i $(dir $<) $(DTC_FLAGS) \
-Wno-interrupts_property \
-ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y) \
-Wno-label_is_string \
-Wno-reg_format \
-Wno-pci_device_bus_num \
-Wno-i2c_bus_reg \
-Wno-spi_bus_reg \
-Wno-avoid_default_addr_size \
-endif \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
$(obj)/%.dtbo: $(src)/%-overlay.dts FORCE
$(call if_changed_dep,dtco)
+endif
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
--
2.27.0
2
1

[PATCH kernel-4.19 01/32] ascend: sharepool: don't enable the vmalloc to use hugepage default
by Yang Yingliang 08 Mar '21
by Yang Yingliang 08 Mar '21
08 Mar '21
From: Ding Tianhong <dingtianhong(a)huawei.com>
ascend inclusion
category: feature
bugzilla: NA
CVE: NA
-------------------------------------------------
The commit 59a57a82fb2a ("mm/vmalloc: Hugepage vmalloc mappings")
would enable the vmalloc for hugepage default when the alloc size
is bigger than the PMD_SIZE, it looks like the transparent hugepage
for mmap, the driver could not control the hugepage accurately and
be break the logic, now the share pool already export the
vmalloc_hugepage_xxx function to control the vmalloc hugepage allocation,
it looks like the static hugepage for vmalloc, so disable the transparent
hugepage function.
This patch also fix the problem of breaking the kabi of vm_struct,
the user could applied it for commercial version.
Fixes: 59a57a82fb2a ("mm/vmalloc: Hugepage vmalloc mappings")
Signed-off-by: Ding Tianhong <dingtianhong(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/share_pool.h | 51 ++++++++++++++++++++++++++++----------
include/linux/vmalloc.h | 1 -
mm/vmalloc.c | 47 ++++++++++++-----------------------
3 files changed, 54 insertions(+), 45 deletions(-)
diff --git a/include/linux/share_pool.h b/include/linux/share_pool.h
index c3120b7b24948..4a18c88d5a10e 100644
--- a/include/linux/share_pool.h
+++ b/include/linux/share_pool.h
@@ -211,15 +211,6 @@ static inline void sp_area_work_around(struct vm_unmapped_area_info *info)
extern struct page *sp_alloc_pages(struct vm_struct *area, gfp_t mask,
unsigned int page_order, int node);
-
-static inline void sp_free_pages(struct page *page, struct vm_struct *area)
-{
- if (PageHuge(page))
- put_page(page);
- else
- __free_pages(page, area->page_order);
-}
-
static inline bool sp_check_vm_share_pool(unsigned long vm_flags)
{
if (enable_ascend_share_pool && (vm_flags & VM_SHARE_POOL))
@@ -264,6 +255,30 @@ extern void *buff_vzalloc_hugepage_user(unsigned long size);
void sp_exit_mm(struct mm_struct *mm);
+static inline bool is_vmalloc_huge(unsigned long vm_flags)
+{
+ if (enable_ascend_share_pool && (vm_flags & VM_HUGE_PAGES))
+ return true;
+
+ return false;
+}
+
+static inline bool is_vmalloc_sharepool(unsigned long vm_flags)
+{
+ if (enable_ascend_share_pool && (vm_flags & VM_SHAREPOOL))
+ return true;
+
+ return false;
+}
+
+static inline void sp_free_pages(struct page *page, struct vm_struct *area)
+{
+ if (PageHuge(page))
+ put_page(page);
+ else
+ __free_pages(page, is_vmalloc_huge(area->flags) ? PMD_SHIFT - PAGE_SHIFT : 0);
+}
+
#else
static inline int sp_group_add_task(int pid, int spg_id)
@@ -400,10 +415,6 @@ static inline struct page *sp_alloc_pages(void *area, gfp_t mask,
return NULL;
}
-static inline void sp_free_pages(struct page *page, struct vm_struct *area)
-{
-}
-
static inline bool sp_check_vm_share_pool(unsigned long vm_flags)
{
return false;
@@ -448,6 +459,20 @@ static inline void *buff_vzalloc_hugepage_user(unsigned long size)
return NULL;
}
+static inline bool is_vmalloc_huge(struct vm_struct *vm)
+{
+ return NULL;
+}
+
+static inline bool is_vmalloc_sharepool(struct vm_struct *vm)
+{
+ return NULL;
+}
+
+static inline void sp_free_pages(struct page *page, struct vm_struct *area)
+{
+}
+
#endif
#endif /* LINUX_SHARE_POOL_H */
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index bb814f6418fd9..298eff5579b21 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -43,7 +43,6 @@ struct vm_struct {
unsigned long size;
unsigned long flags;
struct page **pages;
- unsigned int page_order;
unsigned int nr_pages;
phys_addr_t phys_addr;
const void *caller;
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 37b4762871142..8c70131e0b078 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -2354,6 +2354,7 @@ struct vm_struct *remove_vm_area(const void *addr)
static void __vunmap(const void *addr, int deallocate_pages)
{
struct vm_struct *area;
+ unsigned int page_order = 0;
if (!addr)
return;
@@ -2369,13 +2370,14 @@ static void __vunmap(const void *addr, int deallocate_pages)
return;
}
-#ifdef CONFIG_ASCEND_SHARE_POOL
/* unmap a sharepool vm area will cause meamleak! */
- if (area->flags & VM_SHAREPOOL) {
+ if (is_vmalloc_sharepool(area->flags)) {
WARN(1, KERN_ERR "Memory leak due to vfree() sharepool vm area (%p) !\n", addr);
return;
}
-#endif
+
+ if (is_vmalloc_huge(area->flags))
+ page_order = PMD_SHIFT - PAGE_SHIFT;
debug_check_no_locks_freed(area->addr, get_vm_area_size(area));
debug_check_no_obj_freed(area->addr, get_vm_area_size(area));
@@ -2384,14 +2386,14 @@ static void __vunmap(const void *addr, int deallocate_pages)
if (deallocate_pages) {
int i;
- for (i = 0; i < area->nr_pages; i += 1U << area->page_order) {
+ for (i = 0; i < area->nr_pages; i += 1U << page_order) {
struct page *page = area->pages[i];
BUG_ON(!page);
if (sp_is_enabled())
sp_free_pages(page, area);
else
- __free_pages(page, area->page_order);
+ __free_pages(page, page_order);
}
kvfree(area->pages);
@@ -2589,7 +2591,6 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
area->pages = pages;
area->nr_pages = nr_pages;
- area->page_order = page_order;
for (i = 0; i < area->nr_pages; i += 1U << page_order) {
struct page *page;
@@ -2657,27 +2658,17 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
if (!size || (size >> PAGE_SHIFT) > totalram_pages)
goto fail;
- if (vmap_allow_huge && (pgprot_val(prot) == pgprot_val(PAGE_KERNEL))) {
- unsigned long size_per_node;
-
+ if (vmap_allow_huge && (pgprot_val(prot) == pgprot_val(PAGE_KERNEL)) && is_vmalloc_huge(vm_flags)) {
/*
- * Try huge pages. Only try for PAGE_KERNEL allocations,
- * others like modules don't yet expect huge pages in
- * their allocations due to apply_to_page_range not
- * supporting them.
+ * Alloc huge pages. Only valid for PAGE_KERNEL allocations and
+ * VM_HUGE_PAGES flags.
*/
- size_per_node = size;
- if (node == NUMA_NO_NODE && !sp_is_enabled())
- size_per_node /= num_online_nodes();
- if (size_per_node >= PMD_SIZE) {
- shift = PMD_SHIFT;
- align = max(real_align, 1UL << shift);
- size = ALIGN(real_size, 1UL << shift);
- }
+ shift = PMD_SHIFT;
+ align = max(real_align, 1UL << shift);
+ size = ALIGN(real_size, 1UL << shift);
}
-again:
size = PAGE_ALIGN(size);
area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED |
vm_flags, start, end, node, gfp_mask, caller);
@@ -2706,12 +2697,6 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
return addr;
fail:
- if (shift > PAGE_SHIFT) {
- shift = PAGE_SHIFT;
- align = real_align;
- size = real_size;
- goto again;
- }
if (!area) {
/* Warn for area allocation, page allocations already warn */
@@ -3776,7 +3761,7 @@ static int s_show(struct seq_file *m, void *p)
seq_printf(m, " %pS", v->caller);
if (v->nr_pages)
- seq_printf(m, " pages=%d order=%d", v->nr_pages, v->page_order);
+ seq_printf(m, " pages=%d", v->nr_pages);
if (v->phys_addr)
seq_printf(m, " phys=%pa", &v->phys_addr);
@@ -3796,8 +3781,8 @@ static int s_show(struct seq_file *m, void *p)
if (is_vmalloc_addr(v->pages))
seq_puts(m, " vpages");
- if (sp_is_enabled())
- seq_printf(m, " order=%d", v->page_order);
+ if (is_vmalloc_huge(v->flags))
+ seq_printf(m, " order=%d", PMD_SHIFT - PAGE_SHIFT);
show_numa_info(m, v);
seq_putc(m, '\n');
--
2.25.1
1
31
openEuler inclusion
category: bugfix
bugzilla: https://bugzilla.openeuler.org/show_bug.cgi?id=6
CVE: NA
When performing the out-of-tree kernel 4.19 building, some error
happened saying: cannot touch 'certs/pubring.gpg'. The detail can be
checked in Gitee issue #I39160 or Bug 6 of openeuler bugzilla.
This patch will fix that build error.
Signed-off-by: Zhichang Yuan <erik.yuan(a)arm.com>
Signed-off-by: Steve Capper <Steve.Capper(a)arm.com>
---
certs/Makefile | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/certs/Makefile b/certs/Makefile
index 5053e3c86c97..5e56f9405758 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -5,11 +5,12 @@
obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
ifdef CONFIG_PGP_PRELOAD_PUBLIC_KEYS
-ifneq ($(shell ls certs/pubring.gpg 2> /dev/null), certs/pubring.gpg)
-$(shell touch certs/pubring.gpg)
-endif
-$(obj)/system_certificates.o: certs/pubring.gpg
+$(obj)/system_certificates.o: $(obj)/pubring.gpg
+
+$(obj)/pubring.gpg:
+ $(Q)touch $@
endif
+
obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o
ifneq ($(CONFIG_SYSTEM_BLACKLIST_HASH_LIST),"")
obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o
--
2.23.0
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
4
6
Alain Volmat (1):
i2c: stm32f7: fix configuration of the digital filter
Alexandre Belloni (1):
ARM: dts: lpc32xx: Revert set default clock rate of HCLK PLL
Alexandre Ghiti (1):
riscv: virt_addr_valid must check the address belongs to linear
mapping
Amir Goldstein (1):
ovl: skip getxattr of security labels
Arun Easi (1):
scsi: qla2xxx: Fix crash during driver load on big endian machines
Borislav Petkov (1):
x86/build: Disable CET instrumentation in the kernel for 32-bit too
Bui Quang Minh (1):
bpf: Check for integer overflow when using roundup_pow_of_two()
Edwin Peer (1):
net: watchdog: hold device global xmit lock during tx disable
Fangrui Song (1):
firmware_loader: align .builtin_fw to 8
Felipe Balbi (1):
usb: dwc3: ulpi: fix checkpatch warning
Florian Westphal (1):
netfilter: conntrack: skip identical origin tuple in same zone only
Greg Kroah-Hartman (1):
Linux 4.19.177
Hans de Goede (1):
platform/x86: hp-wmi: Disable tablet-mode reporting by default
Jan Beulich (8):
Xen/x86: don't bail early from clear_foreign_p2m_mapping()
Xen/x86: also check kernel mapping in set_foreign_p2m_mapping()
Xen/gntdev: correct dev_bus_addr handling in gntdev_map_grant_pages()
Xen/gntdev: correct error checking in gntdev_map_grant_pages()
xen-blkback: don't "handle" error by BUG()
xen-netback: don't "handle" error by BUG()
xen-scsiback: don't "handle" error by BUG()
xen-blkback: fix error handling in xen_blkbk_map()
Jozsef Kadlecsik (1):
netfilter: xt_recent: Fix attempt to update deleted entry
Juergen Gross (1):
xen/netback: avoid race in xenvif_rx_ring_slots_available()
Julien Grall (1):
arm/xen: Don't probe xenbus as part of an early initcall
Lai Jiangshan (1):
kvm: check tlbs_dirty directly
Lin Feng (1):
bfq-iosched: Revert "bfq: Fix computation of shallow depth"
Loic Poulain (1):
net: qrtr: Fix port ID for control messages
Lorenzo Bianconi (1):
mt76: dma: fix a possible memory leak in mt76_add_fragment()
Marc Zyngier (1):
arm64: dts: rockchip: Fix PCIe DT properties on rk3399
Miklos Szeredi (3):
ovl: perform vfs_getxattr() with mounter creds
cap: fix conversions on getxattr
ovl: expand warning in ovl_d_real()
Mohammad Athari Bin Ismail (1):
net: stmmac: set TxQ mode back to DCB after disabling CBS
NeilBrown (1):
net: fix iteration for sctp transport seq_files
Norbert Slusarek (1):
net/vmw_vsock: improve locking in vsock_connect_timeout()
Paolo Bonzini (1):
KVM: SEV: fix double locking due to incorrect backport
Randy Dunlap (1):
h8300: fix PREEMPTION build, TI_PRE_COUNT undefined
Russell King (2):
ARM: ensure the signal page contains defined contents
ARM: kexec: fix oops after TLB are invalidated
Sabyrzhan Tasbolatov (2):
net/rds: restrict iovecs length for RDS_CMSG_RDMA_ARGS
net/qrtr: restrict user-controlled length in qrtr_tun_write_iter()
Serge Semin (1):
usb: dwc3: ulpi: Replace CPU-based busyloop with Protocol-based one
Stefano Garzarella (2):
vsock/virtio: update credit only if socket is not closed
vsock: fix locking in vsock_shutdown()
Stefano Stabellini (1):
xen/arm: don't ignore return errors from set_phys_to_machine
Steven Rostedt (VMware) (2):
tracing: Do not count ftrace events in top level enable output
tracing: Check length before giving out the filter buffer
Sven Auhagen (1):
netfilter: flowtable: fix tcp and udp header checksum update
Victor Lu (2):
drm/amd/display: Fix dc_sink kref count in emulated_link_detect
drm/amd/display: Free atomic state after drm_atomic_commit
Makefile | 2 +-
arch/arm/boot/dts/lpc32xx.dtsi | 3 -
arch/arm/include/asm/kexec-internal.h | 12 ++++
arch/arm/kernel/asm-offsets.c | 5 ++
arch/arm/kernel/machine_kexec.c | 20 +++---
arch/arm/kernel/relocate_kernel.S | 38 +++--------
arch/arm/kernel/signal.c | 14 ++--
arch/arm/xen/enlighten.c | 2 -
arch/arm/xen/p2m.c | 6 +-
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
arch/h8300/kernel/asm-offsets.c | 3 +
arch/riscv/include/asm/page.h | 5 +-
arch/x86/Makefile | 6 +-
arch/x86/kvm/svm.c | 1 -
arch/x86/xen/p2m.c | 15 ++---
block/bfq-iosched.c | 8 +--
drivers/block/xen-blkback/blkback.c | 30 +++++----
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 +++--
drivers/i2c/busses/i2c-stm32f7.c | 11 ++-
.../net/ethernet/stmicro/stmmac/stmmac_tc.c | 7 +-
drivers/net/wireless/mediatek/mt76/dma.c | 8 ++-
drivers/net/xen-netback/netback.c | 4 +-
drivers/net/xen-netback/rx.c | 9 ++-
drivers/platform/x86/hp-wmi.c | 14 ++--
drivers/scsi/qla2xxx/qla_tmpl.c | 9 +--
drivers/scsi/qla2xxx/qla_tmpl.h | 2 +-
drivers/usb/dwc3/ulpi.c | 20 ++++--
drivers/xen/gntdev.c | 37 +++++-----
drivers/xen/xen-scsiback.c | 4 +-
drivers/xen/xenbus/xenbus.h | 1 -
drivers/xen/xenbus/xenbus_probe.c | 2 +-
fs/overlayfs/copy_up.c | 15 +++--
fs/overlayfs/inode.c | 2 +
fs/overlayfs/super.c | 13 ++--
include/asm-generic/vmlinux.lds.h | 2 +-
include/linux/netdevice.h | 2 +
include/xen/grant_table.h | 1 +
include/xen/xenbus.h | 2 -
kernel/bpf/stackmap.c | 2 +
kernel/trace/trace.c | 2 +-
kernel/trace/trace_events.c | 3 +-
net/netfilter/nf_conntrack_core.c | 3 +-
net/netfilter/nf_flow_table_core.c | 4 +-
net/netfilter/xt_recent.c | 12 +++-
net/qrtr/qrtr.c | 2 +-
net/qrtr/tun.c | 6 ++
net/rds/rdma.c | 3 +
net/sctp/proc.c | 16 +++--
net/vmw_vsock/af_vsock.c | 13 ++--
net/vmw_vsock/hyperv_transport.c | 4 --
net/vmw_vsock/virtio_transport_common.c | 4 +-
security/commoncap.c | 67 ++++++++++++-------
virt/kvm/kvm_main.c | 3 +-
53 files changed, 295 insertions(+), 204 deletions(-)
create mode 100644 arch/arm/include/asm/kexec-internal.h
--
2.25.1
1
50
From: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 34278
CVE: NA
-------------------------------------------------
Set dentry before goto error handling branch.
fs/resctrlfs.c: In function ‘resctrl_mount’:
fs/resctrlfs.c:419:9: warning: ‘dentry’ may be used uninitialized in this function [-Wmaybe-uninitialized]
return dentry;
^~~~~~
Fixes: 1b70f98921b10 ("arm64/mpam: resctrl: Use resctrl_group_init_alloc() for default group")
Signed-off-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
Reviewed-by: Jian Cheng <cj.chengjian(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
fs/resctrlfs.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/resctrlfs.c b/fs/resctrlfs.c
index 190ad509714d5..df47b105609b9 100644
--- a/fs/resctrlfs.c
+++ b/fs/resctrlfs.c
@@ -351,8 +351,10 @@ static struct dentry *resctrl_mount(struct file_system_type *fs_type,
}
ret = resctrl_group_init_alloc(&resctrl_group_default);
- if (ret < 0)
+ if (ret < 0) {
+ dentry = ERR_PTR(ret);
goto out_schema;
+ }
ret = resctrl_group_create_info_dir(resctrl_group_default.kn, &kn_info);
if (ret) {
--
2.25.1
1
0
Cong Wang (1):
af_key: relax availability checks for skb size calculation
Dave Wysochanski (2):
SUNRPC: Move simple_get_bytes and simple_get_netobj into private
header
SUNRPC: Handle 0 length opaque XDR object data properly
David Collins (1):
regulator: core: avoid regulator_resolve_supply() race condition
Douglas Anderson (1):
regulator: core: Clean enabling always-on regulators + their supplies
Emmanuel Grumbach (1):
iwlwifi: pcie: add a NULL check in iwl_pcie_txq_unmap
Greg Kroah-Hartman (1):
Linux 4.19.176
Johannes Berg (3):
iwlwifi: mvm: take mutex for calling iwl_mvm_get_sync_time()
iwlwifi: pcie: fix context info memory leak
iwlwifi: mvm: guard against device removal in reprobe
Mark Brown (1):
regulator: Fix lockdep warning resolving supplies
Masami Hiramatsu (1):
tracing/kprobe: Fix to support kretprobe events on unloaded modules
Ming Lei (2):
block: don't hold q->sysfs_lock in elevator_init_mq
blk-mq: don't hold q->sysfs_lock in blk_mq_map_swqueue
Olliver Schinagl (1):
regulator: core: enable power when setting up constraints
Pan Bian (1):
chtls: Fix potential resource leak
Peter Gonda (1):
Fix unsynchronized access to sev members through
svm_register_enc_region
Phillip Lougher (3):
squashfs: add more sanity checks in id lookup
squashfs: add more sanity checks in inode lookup
squashfs: add more sanity checks in xattr id lookup
Sibi Sankar (2):
remoteproc: qcom_q6v5_mss: Validate modem blob firmware size before
load
remoteproc: qcom_q6v5_mss: Validate MBA firmware size before load
Steven Rostedt (VMware) (1):
fgraph: Initialize tracing_graph_pause at task creation
Tobin C. Harding (1):
lib/string: Add strscpy_pad() function
Trond Myklebust (1):
pNFS/NFSv4: Try to return invalid layout in pnfs_layout_process()
Makefile | 2 +-
arch/x86/kvm/svm.c | 18 ++--
block/blk-mq.c | 7 --
block/elevator.c | 14 ++--
drivers/crypto/chelsio/chtls/chtls_cm.c | 7 +-
.../wireless/intel/iwlwifi/mvm/debugfs-vif.c | 3 +
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 +-
.../intel/iwlwifi/pcie/ctxt-info-gen3.c | 11 ++-
drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 5 ++
drivers/regulator/core.c | 84 +++++++++++++------
drivers/remoteproc/qcom_q6v5_pil.c | 11 ++-
fs/nfs/pnfs.c | 8 +-
fs/squashfs/export.c | 41 +++++++--
fs/squashfs/id.c | 40 +++++++--
fs/squashfs/squashfs_fs_sb.h | 1 +
fs/squashfs/super.c | 6 +-
fs/squashfs/xattr.h | 10 ++-
fs/squashfs/xattr_id.c | 66 +++++++++++++--
include/linux/kprobes.h | 2 +-
include/linux/string.h | 4 +
include/linux/sunrpc/xdr.h | 3 +-
init/init_task.c | 3 +-
kernel/kprobes.c | 34 ++++++--
kernel/trace/ftrace.c | 2 -
kernel/trace/trace_kprobe.c | 4 +-
lib/string.c | 47 +++++++++--
net/key/af_key.c | 6 +-
net/sunrpc/auth_gss/auth_gss.c | 30 +------
net/sunrpc/auth_gss/auth_gss_internal.h | 45 ++++++++++
net/sunrpc/auth_gss/gss_krb5_mech.c | 31 +------
30 files changed, 375 insertions(+), 173 deletions(-)
create mode 100644 net/sunrpc/auth_gss/auth_gss_internal.h
--
2.25.1
1
25
From: Chenguangli <chenguangli2(a)huawei.com>
driver inclusion
category: feature
bugzilla: NA
-----------------------------------------------------------------------
This module is used to register the hifc driver FC capability to the
SCSI layer.
Signed-off-by: Chenguangli <chenguangli2(a)huawei.com>
Reviewed-by: Zengweiliang <zengweiliang.zengweiliang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/scsi/huawei/Kconfig | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/huawei/Kconfig b/drivers/scsi/huawei/Kconfig
index a9fbdef9b4b38..1fe47e626f568 100644
--- a/drivers/scsi/huawei/Kconfig
+++ b/drivers/scsi/huawei/Kconfig
@@ -3,9 +3,10 @@
#
config SCSI_HUAWEI_FC
- tristate "Huawei devices"
+ tristate "Huawei Fibre Channel Adapter"
depends on PCI && SCSI
depends on SCSI_FC_ATTRS
+ depends on ARM64 || X86_64
default m
---help---
If you have a Fibre Channel PCI card belonging to this class, say Y.
--
2.25.1
1
4
Alexey Dobriyan (1):
Input: i8042 - unbreak Pegatron C15B
Arnd Bergmann (1):
elfcore: fix building with clang
Aurelien Aptel (1):
cifs: report error instead of invalid when revalidating a dentry fails
Benjamin Valentin (1):
Input: xpad - sync supported devices with fork on GitHub
Chenxin Jin (1):
USB: serial: cp210x: add new VID/PID for supporting Teraoka AD2000
Christoph Schemmel (1):
USB: serial: option: Adding support for Cinterion MV31
DENG Qingfang (1):
net: dsa: mv88e6xxx: override existent unicast portvec in port_fdb_add
Dan Carpenter (1):
USB: gadget: legacy: fix an error code in eth_bind()
Dave Hansen (1):
x86/apic: Add extra serialization for non-serializing MSRs
David Howells (1):
rxrpc: Fix deadlock around release of dst cached on udp tunnel
Felix Fietkau (1):
mac80211: fix station rate table updates on assoc
Fengnan Chang (1):
mmc: core: Limit retries when analyse of SDIO tuples fails
Gary Bisson (1):
usb: dwc3: fix clock issue during resume in OTG mode
Greg Kroah-Hartman (1):
Linux 4.19.175
Gustavo A. R. Silva (1):
smb3: Fix out-of-bounds bug in SMB2_negotiate()
Heiko Stuebner (1):
usb: dwc2: Fix endpoint direction check in ep_from_windex
Hugh Dickins (1):
mm: thp: fix MADV_REMOVE deadlock on shmem THP
Jeremy Figgins (1):
USB: usblp: don't call usb_set_interface if there's a single alt
Josh Poimboeuf (1):
x86/build: Disable CET instrumentation in the kernel
Liangyan (1):
ovl: fix dentry leak in ovl_get_redirect
Marc Zyngier (1):
genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is
set
Mathias Nyman (1):
xhci: fix bounce buffer usage for non-sg list case
Muchun Song (4):
mm: hugetlbfs: fix cannot migrate the fallocated HugeTLB page
mm: hugetlb: fix a race between freeing and dissolving the page
mm: hugetlb: fix a race between isolating and freeing page
mm: hugetlb: remove VM_BUG_ON_PAGE from page_huge_active
Nadav Amit (1):
iommu/vt-d: Do not use flush-queue when caching-mode is on
Pho Tran (1):
USB: serial: cp210x: add pid/vid for WSDA-200-USB
Roman Gushchin (1):
memblock: do not start bottom-up allocations with kernel_end
Russell King (1):
ARM: footbridge: fix dc21285 PCI configuration accessors
Sean Christopherson (1):
KVM: SVM: Treat SVM as unsupported when running as an SEV guest
Stefan Chulski (1):
net: mvpp2: TCAM entry enable should be written after SRAM data
Thorsten Leemhuis (1):
nvme-pci: avoid the deepest sleep state on Kingston A2000 SSDs
Vadim Fedorenko (1):
net: ip_tunnel: fix mtu calculation
Wang ShaoBo (1):
kretprobe: Avoid re-registration of the same kretprobe earlier
Xiao Ni (1):
md: Set prev_flush_start and flush_bio in an atomic way
Xie He (1):
net: lapb: Copy the skb before sending a packet
Yoshihiro Shimoda (1):
usb: renesas_usbhs: Clear pipe running flag in usbhs_pkt_pop()
Zyta Szpak (1):
arm64: dts: ls1046a: fix dcfg address range
Makefile | 8 +--
arch/arm/mach-footbridge/dc21285.c | 12 ++---
.../arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 2 +-
arch/x86/Makefile | 3 ++
arch/x86/include/asm/apic.h | 10 ----
arch/x86/include/asm/barrier.h | 18 +++++++
arch/x86/kernel/apic/apic.c | 4 ++
arch/x86/kernel/apic/x2apic_cluster.c | 6 ++-
arch/x86/kernel/apic/x2apic_phys.c | 6 ++-
arch/x86/kvm/svm.c | 5 ++
drivers/input/joystick/xpad.c | 17 ++++++-
drivers/input/serio/i8042-x86ia64io.h | 2 +
drivers/iommu/intel-iommu.c | 6 +++
drivers/md/md.c | 2 +
drivers/mmc/core/sdio_cis.c | 6 +++
drivers/net/dsa/mv88e6xxx/chip.c | 6 ++-
.../net/ethernet/marvell/mvpp2/mvpp2_prs.c | 10 ++--
drivers/nvme/host/pci.c | 2 +
drivers/usb/class/usblp.c | 19 ++++---
drivers/usb/dwc2/gadget.c | 8 +--
drivers/usb/dwc3/core.c | 2 +-
drivers/usb/gadget/legacy/ether.c | 4 +-
drivers/usb/host/xhci-ring.c | 31 +++++++-----
drivers/usb/renesas_usbhs/fifo.c | 1 +
drivers/usb/serial/cp210x.c | 2 +
drivers/usb/serial/option.c | 6 +++
fs/afs/main.c | 6 +--
fs/cifs/dir.c | 22 ++++++++-
fs/cifs/smb2pdu.h | 2 +-
fs/hugetlbfs/inode.c | 3 +-
fs/overlayfs/dir.c | 2 +-
include/linux/elfcore.h | 22 +++++++++
include/linux/hugetlb.h | 3 ++
include/linux/msi.h | 6 +++
kernel/Makefile | 1 -
kernel/elfcore.c | 26 ----------
kernel/irq/msi.c | 44 ++++++++---------
kernel/kprobes.c | 4 ++
mm/huge_memory.c | 37 ++++++++------
mm/hugetlb.c | 48 ++++++++++++++++--
mm/memblock.c | 49 +++----------------
net/ipv4/ip_tunnel.c | 16 +++---
net/lapb/lapb_out.c | 3 +-
net/mac80211/driver-ops.c | 5 +-
net/mac80211/rate.c | 3 +-
net/rxrpc/af_rxrpc.c | 6 +--
46 files changed, 307 insertions(+), 199 deletions(-)
delete mode 100644 kernel/elfcore.c
--
2.25.1
1
39

Re: [PATCH] kbuild fix: keep the original function in Makefile.lib for non-RPi
by Zheng Zengkai 08 Mar '21
by Zheng Zengkai 08 Mar '21
08 Mar '21
Hi Yafen,
> ---------------------- [WARNING] checkpatch ----------------------
>
> total: 0 errors, 1 warnings, 27 lines checked
>
> WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
> #84:
> /bin/sh: -c: line 0: `set -e; echo ' DTCO arch/arm64/boot/dts/overlays/act-led.dtbo'; mkdir -p arch/arm64/boot/dts/overlays/ ; gcc -E -Wp,-MMD,arch/arm64/boot/dts/overlays/.act-led.dtbo.d.pre.tmp -nostdinc -I./scripts/dtc/include-prefixes -undef -D__DTS__ -x assembler-with-cpp -o arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp arch/arm64/boot/dts/overlays/act-led-overlay.dts ; ./scripts/dtc/dtc -@ -H epapr -O dtb -o arch/arm64/boot/dts/overlays/act-led.dtbo -b 0 -i arch/arm64/boot/dts/overlays/ -Wno-interrupt_provider -Wno-unit_address_vs_reg -Wno-unit_address_format -Wno-gpios_property -Wno-avoid_unnecessary_addr_size -Wno-alias_paths -Wno-graph_child_address -Wno-simple_bus_reg -Wno-unique_unit_address -Wno-pci_device_reg -Wno-interrupts_property ifeq (y,y) -Wno-label_is_string -Wno-reg_format -Wno-pci_device_bus_num -Wno-i2c_bus_reg -Wno-spi_bus_reg -Wno-avoid_default_addr_size endif -d arch/arm64/boot/dts/overlays/.act-led.dtbo.d.dtc.tmp arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp ; cat ...; rm -f arch/arm64/boot/dts/overlays/.act-led.dtbo.d'
>
> total: 0 errors, 1 warnings, 27 lines checked
>
> NOTE: For some of the reported defects, checkpatch may be able to
> mechanically convert to the typical style using --fix or --fix-inplace.
>
> kbuild-fix-keep-the-original-function-in-Makefile.lib-for-non-RPi.patch has style problems, please review.
This patch has style problems, please review.
Thanks!
2
1

[PATCH] kbuild fix: keep the original function in Makefile.lib for non-RPi
by fangyafenqidai@163.com 08 Mar '21
by fangyafenqidai@163.com 08 Mar '21
08 Mar '21
From: Fang Yafen <yafen(a)iscas.ac.cn>
Fix the following compile error when using bcm2711_defconfig (for RPi).
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `set -e; echo ' DTCO arch/arm64/boot/dts/overlays/act-led.dtbo'; mkdir -p arch/arm64/boot/dts/overlays/ ; gcc -E -Wp,-MMD,arch/arm64/boot/dts/overlays/.act-led.dtbo.d.pre.tmp -nostdinc -I./scripts/dtc/include-prefixes -undef -D__DTS__ -x assembler-with-cpp -o arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp arch/arm64/boot/dts/overlays/act-led-overlay.dts ; ./scripts/dtc/dtc -@ -H epapr -O dtb -o arch/arm64/boot/dts/overlays/act-led.dtbo -b 0 -i arch/arm64/boot/dts/overlays/ -Wno-interrupt_provider -Wno-unit_address_vs_reg -Wno-unit_address_format -Wno-gpios_property -Wno-avoid_unnecessary_addr_size -Wno-alias_paths -Wno-graph_child_address -Wno-simple_bus_reg -Wno-unique_unit_address -Wno-pci_device_reg -Wno-interrupts_property ifeq (y,y) -Wno-label_is_string -Wno-reg_format -Wno-pci_device_bus_num -Wno-i2c_bus_reg -Wno-spi_bus_reg -Wno-avoid_default_addr_size endif -d arch/arm64/boot/dts/overlays/.act-led.dtbo.d.dtc.tmp arch/arm64/boot/dts/overlays/.act-led.dtbo.dts.tmp ; cat ...; rm -f arch/arm64/boot/dts/overlays/.act-led.dtbo.d'
make[2]: *** [scripts/Makefile.lib;363: arch/arm64/boot/dts/overlays/act-led.dtbo] Error 1
make[2]: *** Waiting for unfinished jobs....
Related patches:
ffa2d13ccc3 BCM2708: Add core Device Tree support
4894352ec98 kbuild: Silence unavoidable dtc overlay warnings
a4a4d07f0cf kbuild: keep the original function for non-RPi
Signed-off-by: Fang Yafen <yafen(a)iscas.ac.cn>
---
scripts/Makefile.lib | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index c23e3ae7ef40..a0e0e2543165 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -342,25 +342,25 @@ endef
$(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
$(call if_changed_rule,dtc,yaml)
+ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y)
quiet_cmd_dtco = DTCO $@
cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; \
$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
$(DTC) -@ -H epapr -O dtb -o $@ -b 0 \
-i $(dir $<) $(DTC_FLAGS) \
-Wno-interrupts_property \
-ifeq ($(CONFIG_OPENEULER_RASPBERRYPI),y) \
-Wno-label_is_string \
-Wno-reg_format \
-Wno-pci_device_bus_num \
-Wno-i2c_bus_reg \
-Wno-spi_bus_reg \
-Wno-avoid_default_addr_size \
-endif \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
$(obj)/%.dtbo: $(src)/%-overlay.dts FORCE
$(call if_changed_dep,dtco)
+endif
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
--
2.23.0
1
0

[PATCH openEuler-21.03 v3 1/2] arm64: Add memmap parameter and register pmem
by zhuling8@huawei.com 08 Mar '21
by zhuling8@huawei.com 08 Mar '21
08 Mar '21
From: ZhuLing <zhuling8(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: NA
Register pmem in arm64:
Use memmap(memmap=nn[KMG]!ss[KMG]) reserve memory and
e820(driver/nvdimm/e820.c) function to register persistent
memory in arm64. when the kernel restart or update, the data
in PMEM will not be lost and can be loaded faster. this is a
general features.
driver/nvdimm/e820.c:
The function of this file is scan "iomem_resource" and take
advantage of nvdimm resource discovery mechanism by registering
a resource named "Persistent Memory (legacy)", this function
doesn't depend on architecture.
We will push the feature to linux kernel community and discuss to
modify the file name. because people have a mistaken notion that
the e820.c is depend on x86.
If you want use this features, you need do as follows:
1.Reserve memory: add memmap to reserve memory in grub.cfg
memmap=nn[KMG]!ss[KMG] exp:memmap=100K!0x1a0000000.
2.Insmod nd_e820.ko: modprobe nd_e820.
3.Check pmem device in /dev exp: /dev/pmem0
Signed-off-by: ZhuLing <zhuling8(a)huawei.com>
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
Acked-by: Hanjun Guo <guohanjun(a)huawei.com>
---
arch/arm64/Kconfig | 21 ++++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/pmem.c | 35 +++++++++++++++++
arch/arm64/kernel/setup.c | 10 +++++
arch/arm64/mm/init.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/Kconfig | 5 +++
drivers/nvdimm/Makefile | 2 +-
7 files changed, 170 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c451137..326f26d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -360,6 +360,27 @@ config ARM64_CPU_PARK
config ARCH_HAS_CPU_RELAX
def_bool y
+config ARM64_PMEM_RESERVE
+ bool "Reserve memory for persistent storage"
+ default n
+ help
+ Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve
+ memory for persistent storage.
+
+ Say y here to enable this feature.
+
+config ARM64_PMEM_LEGACY_DEVICE
+ bool "Create persistent storage"
+ depends on BLK_DEV
+ depends on LIBNVDIMM
+ select ARM64_PMEM_RESERVE
+ help
+ Use reserved memory for persistent storage when the kernel
+ restart or update. the data in PMEM will not be lost and
+ can be loaded faster.
+
+ Say y if unsure.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 967cb3c..be996f3 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_ARM64_MTE) += mte.o
obj-$(CONFIG_MPAM) += mpam/
+obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c
new file mode 100644
index 0000000..16eaf70
--- /dev/null
+++ b/arch/arm64/kernel/pmem.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Derived from x86 and arm64 implement PMEM.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+static int found(struct resource *res, void *data)
+{
+ return 1;
+}
+
+static int __init register_e820_pmem(void)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+ IORESOURCE_MEM, 0, -1, NULL, found);
+ if (rc <= 0)
+ return 0;
+
+ /*
+ * See drivers/nvdimm/e820.c for the implementation, this is
+ * simply here to trigger the module to load on demand.
+ */
+ pdev = platform_device_alloc("e820_pmem", -1);
+
+ return platform_device_add(pdev);
+}
+device_initcall(register_e820_pmem);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 5e282d3..84c71c8 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -57,6 +57,10 @@
static int num_standard_resources;
static struct resource *standard_resources;
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+extern struct resource pmem_res;
+#endif
+
phys_addr_t __fdt_pointer __initdata;
/*
@@ -270,6 +274,12 @@ static void __init request_standard_resources(void)
request_resource(res, &pin_memory_resource);
#endif
}
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ if (pmem_res.end && pmem_res.start)
+ request_resource(&iomem_resource, &pmem_res);
+#endif
+
}
static int __init reserve_memblock_reserved_regions(void)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b343744..f22faea 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -66,6 +66,18 @@ EXPORT_SYMBOL(memstart_addr);
phys_addr_t arm64_dma_phys_limit __ro_after_init;
phys_addr_t arm64_dma32_phys_limit __ro_after_init;
+static unsigned long long pmem_size, pmem_start;
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+struct resource pmem_res = {
+ .name = "Persistent Memory (legacy)",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY
+};
+#endif
+
#ifndef CONFIG_KEXEC_CORE
static void __init reserve_crashkernel(void)
{
@@ -378,6 +390,87 @@ static int __init reserve_park_mem(void)
}
#endif
+static int __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start)
+{
+ if (!memblock_is_region_memory(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region is not memory!\n");
+ return -EINVAL;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region overlaps reserved memory!\n");
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve mem: base address is not 2MB aligned!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init parse_memmap_one(char *p)
+{
+ char *oldp;
+ phys_addr_t start_at, mem_size;
+
+ if (!p)
+ return -EINVAL;
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
+
+ if (!mem_size)
+ return -EINVAL;
+
+ mem_size = PAGE_ALIGN(mem_size);
+
+ if (*p == '!') {
+ start_at = memparse(p+1, &p);
+
+ if (is_mem_valid(mem_size, start_at) != 0)
+ return -EINVAL;
+
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ start_at, start_at + mem_size, mem_size >> 20);
+ pmem_start = start_at;
+ pmem_size = mem_size;
+ } else
+ pr_info("Unrecognized memmap option, please check the parameter.\n");
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+ while (str) {
+ char *k = strchr(str, ',');
+
+ if (k)
+ *k++ = 0;
+
+ parse_memmap_one(str);
+ str = k;
+ }
+
+ return 0;
+}
+early_param("memmap", parse_memmap_opt);
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+static void __init reserve_pmem(void)
+{
+ memblock_remove(pmem_start, pmem_size);
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ pmem_start, pmem_start + pmem_size, pmem_size >> 20);
+ pmem_res.start = pmem_start;
+ pmem_res.end = pmem_start + pmem_size - 1;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -511,6 +604,10 @@ void __init arm64_memblock_init(void)
reserve_elfcorehdr();
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ reserve_pmem();
+#endif
+
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
dma_contiguous_reserve(arm64_dma32_phys_limit);
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index b7d1eb3..ce4de75 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -132,3 +132,8 @@ config NVDIMM_TEST_BUILD
infrastructure.
endif
+
+config PMEM_LEGACY
+ tristate "Pmem_legacy"
+ select X86_PMEM_LEGACY if X86
+ select ARM64_PMEM_LEGACY_DEVICE if ARM64
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 29203f3..6f8dc92 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
-obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_PMEM_LEGACY) += nd_e820.o
obj-$(CONFIG_OF_PMEM) += of_pmem.o
obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
--
2.9.5
1
1

08 Mar '21
From: ZhuLing <zhuling8(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: NA
Register pmem in arm64:
Use memmap(memmap=nn[KMG]!ss[KMG]) reserve memory and
e820(driver/nvdimm/e820.c) function to register persistent
memory in arm64. when the kernel restart or update, the data
in PMEM will not be lost and can be loaded faster. this is a
general features.
driver/nvdimm/e820.c:
The function of this file is scan "iomem_resource" and take
advantage of nvdimm resource discovery mechanism by registering
a resource named "Persistent Memory (legacy)", this function
doesn't depend on architecture.
We will push the feature to linux kernel community and discuss to
modify the file name. because people have a mistaken notion that
the e820.c is depend on x86.
If you want use this features, you need do as follows:
1.Reserve memory: add memmap to reserve memory in grub.cfg
memmap=nn[KMG]!ss[KMG] exp:memmap=100K!0x1a0000000.
2.Insmod nd_e820.ko: modprobe nd_e820.
3.Check pmem device in /dev exp: /dev/pmem0
Signed-off-by: ZhuLing <zhuling8(a)huawei.com>
---
arch/arm64/Kconfig | 21 +++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/pmem.c | 35 ++++++++++++++
arch/arm64/kernel/setup.c | 10 ++++
arch/arm64/mm/init.c | 97 ++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/Kconfig | 5 ++
drivers/nvdimm/Makefile | 2 +-
7 files changed, 170 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c451137ab..326f26d40 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -360,6 +360,27 @@ config ARM64_CPU_PARK
config ARCH_HAS_CPU_RELAX
def_bool y
+config ARM64_PMEM_RESERVE
+ bool "Reserve memory for persistent storage"
+ default n
+ help
+ Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve
+ memory for persistent storage.
+
+ Say y here to enable this feature.
+
+config ARM64_PMEM_LEGACY_DEVICE
+ bool "Create persistent storage"
+ depends on BLK_DEV
+ depends on LIBNVDIMM
+ select ARM64_PMEM_RESERVE
+ help
+ Use reserved memory for persistent storage when the kernel
+ restart or update. the data in PMEM will not be lost and
+ can be loaded faster.
+
+ Say y if unsure.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 967cb3c6d..be996f3c1 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_ARM64_MTE) += mte.o
obj-$(CONFIG_MPAM) += mpam/
+obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c
new file mode 100644
index 000000000..16eaf706f
--- /dev/null
+++ b/arch/arm64/kernel/pmem.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Derived from x86 and arm64 implement PMEM.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+static int found(struct resource *res, void *data)
+{
+ return 1;
+}
+
+static int __init register_e820_pmem(void)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+ IORESOURCE_MEM, 0, -1, NULL, found);
+ if (rc <= 0)
+ return 0;
+
+ /*
+ * See drivers/nvdimm/e820.c for the implementation, this is
+ * simply here to trigger the module to load on demand.
+ */
+ pdev = platform_device_alloc("e820_pmem", -1);
+
+ return platform_device_add(pdev);
+}
+device_initcall(register_e820_pmem);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 5e282d31a..84c71c88d 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -57,6 +57,10 @@
static int num_standard_resources;
static struct resource *standard_resources;
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+extern struct resource pmem_res;
+#endif
+
phys_addr_t __fdt_pointer __initdata;
/*
@@ -270,6 +274,12 @@ static void __init request_standard_resources(void)
request_resource(res, &pin_memory_resource);
#endif
}
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ if (pmem_res.end && pmem_res.start)
+ request_resource(&iomem_resource, &pmem_res);
+#endif
+
}
static int __init reserve_memblock_reserved_regions(void)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index b3437440d..f22faea1a 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -66,6 +66,18 @@ EXPORT_SYMBOL(memstart_addr);
phys_addr_t arm64_dma_phys_limit __ro_after_init;
phys_addr_t arm64_dma32_phys_limit __ro_after_init;
+static unsigned long long pmem_size, pmem_start;
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+struct resource pmem_res = {
+ .name = "Persistent Memory (legacy)",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY
+};
+#endif
+
#ifndef CONFIG_KEXEC_CORE
static void __init reserve_crashkernel(void)
{
@@ -378,6 +390,87 @@ static int __init reserve_park_mem(void)
}
#endif
+static int __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start)
+{
+ if (!memblock_is_region_memory(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region is not memory!\n");
+ return -EINVAL;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region overlaps reserved memory!\n");
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve mem: base address is not 2MB aligned!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init parse_memmap_one(char *p)
+{
+ char *oldp;
+ phys_addr_t start_at, mem_size;
+
+ if (!p)
+ return -EINVAL;
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
+
+ if (!mem_size)
+ return -EINVAL;
+
+ mem_size = PAGE_ALIGN(mem_size);
+
+ if (*p == '!') {
+ start_at = memparse(p+1, &p);
+
+ if (is_mem_valid(mem_size, start_at) != 0)
+ return -EINVAL;
+
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ start_at, start_at + mem_size, mem_size >> 20);
+ pmem_start = start_at;
+ pmem_size = mem_size;
+ } else
+ pr_info("Unrecognized memmap option, please check the parameter.\n");
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+ while (str) {
+ char *k = strchr(str, ',');
+
+ if (k)
+ *k++ = 0;
+
+ parse_memmap_one(str);
+ str = k;
+ }
+
+ return 0;
+}
+early_param("memmap", parse_memmap_opt);
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+static void __init reserve_pmem(void)
+{
+ memblock_remove(pmem_start, pmem_size);
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ pmem_start, pmem_start + pmem_size, pmem_size >> 20);
+ pmem_res.start = pmem_start;
+ pmem_res.end = pmem_start + pmem_size - 1;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -511,6 +604,10 @@ void __init arm64_memblock_init(void)
reserve_elfcorehdr();
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ reserve_pmem();
+#endif
+
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
dma_contiguous_reserve(arm64_dma32_phys_limit);
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index b7d1eb38b..ce4de7526 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -132,3 +132,8 @@ config NVDIMM_TEST_BUILD
infrastructure.
endif
+
+config PMEM_LEGACY
+ tristate "Pmem_legacy"
+ select X86_PMEM_LEGACY if X86
+ select ARM64_PMEM_LEGACY_DEVICE if ARM64
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 29203f3d3..6f8dc9242 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
-obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_PMEM_LEGACY) += nd_e820.o
obj-$(CONFIG_OF_PMEM) += of_pmem.o
obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
--
2.19.1
3
4
各位好,
根据前期沟通,OSV、驱动兼容性SIG都对内核接口兼容性提出了诉求。根据前期
沟通的信息,以及收集的驱动接口使用情况,形成一份 20.03 LTS SP1 SP2 兼容
性 KABI 白名单初稿,请大家评审。
KABI (Kernel Application Binary Interface) 兼容,即内核与驱动的二进制兼容。
就是驱动不用重新编译,就可以在新内核上安装使用。如果驱动用到的接口都
是兼容的,那么驱动就可以不用重新编译就可以在新版本安装使用。上游社区
考虑到便于开发、和防止架构腐化,不考虑 KABI 的兼容性。业界的 KABI 兼容
都是由 Linux 发行版来做的,而且兼容的接口越多、维护时间越长,维护成本
也越高。
openEuler 通过多次与下游OSV和驱动团队交流,根据下游反馈的诉求,
openEuler 20.03 LTS SP1、SP2 版本,提供一定范围的 KABI 兼容能力,目的是
使常用的板卡驱动,在SP1、后续的 SP1 update 版本、SP2及SP2 update版本能
兼容。
kabi 兼容列表白名单的主要输入是驱动(ko),我们根据下游的反馈,收集到
部分常用驱动,作为兼容的目标,驱动列表如下。
ARM64 版本拟兼容的驱动(ko)列表
|amdgpu.ko bnx2.ko bnx2x.ko bnxt_en.ko bnxt_re.ko hclge.ko hclgevf.ko hifc.ko hinic.ko hnae3.ko hns3.ko i40e.ko ice.ko igb.ko ixgbe.ko ixgbevf.ko lpfc.ko megaraid_sas.ko mlx4_core.ko mlx4_ib.ko mlx5_core.ko mlx5_ib.ko mpt3sas.ko nouveau.ko nvme.ko qed.ko qede.ko qla2xxx.ko smartpqi.ko tg3.ko txgbe.ko |
X86 版本拟兼容的驱动(ko)列表
|amdgpu.ko bnx2.ko bnx2x.ko bnxt_en.ko bnxt_re.ko hifc.ko hinic.ko i40e.ko ice.ko igb.ko ixgbe.ko ixgbevf.ko lpfc.ko megaraid_sas.ko mlx4_core.ko mlx4_ib.ko mlx5_core.ko mlx5_ib.ko mpt3sas.ko nouveau.ko nvme.ko qed.ko qede.ko qla2xxx.ko smartpqi.ko tg3.ko txgbe.ko |
我们收集了上表中驱动使用到接口,形成了一份 kabi 白名单列表初稿,请大家评审。
重要的说明和提示:
1. 上述列表中多数驱动,还没有针对 openEuler SP1 的正式二进制版本,因此我们
根据开源的版本或相近的版本收集了相关 kabi 列表,可能与板卡厂商的最终发布
的版本存在少量差异。下游OSV或驱动团队如果发现有接口没在给出的列表中的,
可以在评审过程中提出来。
2. 如果有新增 KABI 兼容性的诉求,需要给出需要兼容的 kabi 接口名称,以及使用
到的驱动名称,以方便评估。
3. 评审反馈,可以在 issue 中反馈,https://gitee.com/openeuler/kernel/issues/I3ABVJ
也可以通过回复邮件反馈。
4. 收集评审反馈信息的时间为1周,截止到下周五(3月12日)下午17:00.
---
openEuler kernel SIG, 2021-3-6
---
附1:ARM64 平台 KABI 白名单列表初稿(1905个)
acpi_bus_get_device
acpi_check_dsm
acpi_dev_found
acpi_disabled
acpi_dma_configure
acpi_evaluate_dsm
acpi_evaluate_object
acpi_format_exception
acpi_gbl_FADT
acpi_get_devices
acpi_get_handle
acpi_get_name
acpi_get_table
acpi_gsi_to_irq
acpi_handle_printk
acpi_has_method
acpi_lid_open
acpi_os_map_memory
acpi_os_unmap_memory
acpi_register_gsi
acpi_unregister_gsi
add_timer
add_wait_queue
add_wait_queue_exclusive
admin_timeout
alloc_chrdev_region
alloc_cpu_rmap
__alloc_disk_node
alloc_etherdev_mqs
alloc_netdev_mqs
alloc_pages_current
__alloc_pages_nodemask
__alloc_percpu
__alloc_skb
__alloc_workqueue_key
__arch_clear_user
__arch_copy_from_user
__arch_copy_in_user
__arch_copy_to_user
arch_timer_read_counter
arch_wb_cache_pmem
arm64_const_caps_ready
arp_tbl
async_schedule
_atomic_dec_and_lock
atomic_notifier_call_chain
atomic_notifier_chain_register
atomic_notifier_chain_unregister
attribute_container_find_class_device
autoremove_wake_function
backlight_device_register
backlight_device_unregister
backlight_force_update
bdevname
bdev_read_only
bdget_disk
_bin2bcd
bio_add_page
bio_alloc_bioset
bio_clone_fast
bio_endio
bio_free_pages
bio_init
bio_put
bioset_exit
bioset_init
__bitmap_and
__bitmap_andnot
__bitmap_clear
__bitmap_complement
__bitmap_equal
bitmap_find_free_region
bitmap_find_next_zero_area_off
bitmap_free
__bitmap_intersects
__bitmap_or
__bitmap_parse
bitmap_parselist
bitmap_print_to_pagebuf
bitmap_release_region
__bitmap_set
__bitmap_weight
__bitmap_xor
bitmap_zalloc
bit_wait
blk_alloc_queue
blk_check_plugged
blk_cleanup_queue
blkdev_get_by_path
blkdev_issue_discard
blkdev_issue_write_same
blkdev_issue_zeroout
blkdev_put
blk_execute_rq
blk_execute_rq_nowait
blk_finish_plug
blk_get_queue
blk_get_request
blk_mq_alloc_tag_set
blk_mq_complete_request
blk_mq_end_request
blk_mq_free_request
blk_mq_free_tag_set
blk_mq_init_queue
blk_mq_map_queues
blk_mq_pci_map_queues
blk_mq_quiesce_queue
blk_mq_run_hw_queues
blk_mq_start_request
blk_mq_tagset_busy_iter
blk_mq_tag_to_rq
blk_mq_unique_tag
blk_mq_unquiesce_queue
blk_mq_update_nr_hw_queues
blk_put_queue
blk_put_request
blk_queue_bounce_limit
blk_queue_dma_alignment
blk_queue_flag_clear
blk_queue_flag_set
blk_queue_io_min
blk_queue_io_opt
blk_queue_logical_block_size
blk_queue_make_request
blk_queue_max_discard_sectors
blk_queue_max_hw_sectors
blk_queue_max_segments
blk_queue_max_segment_size
blk_queue_max_write_same_sectors
blk_queue_physical_block_size
blk_queue_rq_timeout
blk_queue_segment_boundary
blk_queue_split
blk_queue_stack_limits
blk_queue_update_dma_alignment
blk_queue_virt_boundary
blk_queue_write_cache
blk_rq_append_bio
blk_rq_count_integrity_sg
blk_rq_map_integrity_sg
blk_rq_map_kern
blk_rq_map_sg
blk_rq_map_user_iov
blk_rq_unmap_user
blk_set_stacking_limits
blk_start_plug
blk_status_to_errno
blk_verify_command
blocking_notifier_call_chain
blocking_notifier_chain_register
blocking_notifier_chain_unregister
bpf_prog_add
bpf_prog_inc
bpf_prog_put
bpf_trace_run1
bpf_trace_run2
bpf_trace_run3
bpf_trace_run5
bpf_warn_invalid_xdp_action
bsg_job_done
btree_destroy
btree_geo32
btree_geo64
btree_get_prev
btree_init
btree_insert
btree_last
btree_lookup
btree_remove
btree_update
build_skb
cache_line_size
call_netdevice_notifiers
call_rcu_sched
call_srcu
call_usermodehelper
cancel_delayed_work
cancel_delayed_work_sync
cancel_work_sync
capable
cdev_add
cdev_del
cdev_init
__chash_table_copy_in
__chash_table_copy_out
__check_object_size
__class_create
class_destroy
__class_register
class_unregister
_cleanup_srcu_struct
clk_get_rate
commit_creds
compat_alloc_user_space
complete
complete_all
complete_and_exit
completion_done
component_add
component_del
_cond_resched
console_lock
console_unlock
__const_udelay
consume_skb
cpu_bit_bitmap
cpufreq_quick_get
__cpuhp_remove_state
__cpuhp_setup_state
cpu_hwcap_keys
cpu_hwcaps
cpumask_local_spread
cpumask_next
cpumask_next_and
cpu_number
__cpu_online_mask
__cpu_possible_mask
__cpu_present_mask
cpus_read_lock
cpus_read_unlock
crc32c
crc32_le
crc8
crc8_populate_msb
crc_t10dif
crypto_ahash_digest
crypto_ahash_final
crypto_ahash_setkey
crypto_alloc_ahash
crypto_destroy_tfm
crypto_register_shash
crypto_unregister_shash
csum_ipv6_magic
csum_partial
csum_tcpudp_nofold
_ctype
dcb_getapp
dcb_ieee_delapp
dcb_ieee_getapp_mask
dcb_ieee_setapp
dcbnl_cee_notify
dcb_setapp
debugfs_create_atomic_t
debugfs_create_dir
debugfs_create_file
debugfs_create_symlink
debugfs_create_u16
debugfs_create_u32
debugfs_create_u64
debugfs_create_u8
debugfs_lookup
debugfs_remove
default_llseek
default_wake_function
__delay
delayed_work_timer_fn
del_gendisk
del_timer
del_timer_sync
destroy_workqueue
dev_add_pack
dev_addr_add
dev_addr_del
dev_base_lock
dev_close
dev_driver_string
_dev_err
__dev_get_by_index
dev_get_by_index
dev_get_by_index_rcu
dev_get_by_name
dev_get_iflink
dev_get_stats
device_add_disk
device_create
device_create_file
device_destroy
device_link_add
device_release_driver
device_remove_file
device_reprobe
device_set_wakeup_capable
device_set_wakeup_enable
_dev_info
__dev_kfree_skb_any
__dev_kfree_skb_irq
devlink_alloc
devlink_free
devlink_param_driverinit_value_get
devlink_param_driverinit_value_set
devlink_params_register
devlink_params_unregister
devlink_param_value_changed
devlink_port_attrs_set
devlink_port_register
devlink_port_type_clear
devlink_port_type_eth_set
devlink_port_type_ib_set
devlink_port_unregister
devlink_region_create
devlink_region_destroy
devlink_region_shapshot_id_get
devlink_region_snapshot_create
devlink_register
devlink_unregister
dev_mc_add
dev_mc_add_excl
dev_mc_del
devm_free_irq
devm_hwmon_device_register_with_groups
devm_ioremap
devm_iounmap
devm_kfree
devm_kmalloc
devm_kmemdup
devm_mdiobus_alloc_size
devm_request_threaded_irq
_dev_notice
dev_open
dev_printk
dev_queue_xmit
dev_remove_pack
dev_set_mac_address
dev_set_mtu
dev_set_promiscuity
dev_trans_start
dev_uc_add
dev_uc_add_excl
dev_uc_del
_dev_warn
disable_irq
disable_irq_nosync
dma_alloc_from_dev_coherent
dma_common_get_sgtable
dma_common_mmap
dma_fence_add_callback
dma_fence_array_create
dma_fence_context_alloc
dma_fence_free
dma_fence_get_status
dma_fence_init
dma_fence_release
dma_fence_signal
dma_fence_signal_locked
dma_fence_wait_any_timeout
dma_fence_wait_timeout
dma_get_required_mask
dmam_alloc_coherent
dmam_free_coherent
dma_pool_alloc
dma_pool_create
dma_pool_destroy
dma_pool_free
dma_release_from_dev_coherent
dmi_check_system
dmi_get_system_info
dmi_match
__do_once_done
__do_once_start
do_wait_intr
down
downgrade_write
down_interruptible
down_read
down_read_trylock
down_timeout
down_trylock
down_write
down_write_killable
down_write_trylock
dput
dql_completed
dql_reset
drain_workqueue
driver_create_file
driver_for_each_device
driver_remove_file
drm_add_edid_modes
drm_add_modes_noedid
drm_atomic_add_affected_connectors
drm_atomic_add_affected_planes
drm_atomic_commit
drm_atomic_get_connector_state
drm_atomic_get_crtc_state
drm_atomic_get_plane_state
drm_atomic_helper_check
drm_atomic_helper_check_modeset
drm_atomic_helper_check_planes
drm_atomic_helper_check_plane_state
drm_atomic_helper_cleanup_planes
drm_atomic_helper_commit
drm_atomic_helper_commit_cleanup_done
drm_atomic_helper_commit_hw_done
__drm_atomic_helper_connector_destroy_state
drm_atomic_helper_connector_destroy_state
__drm_atomic_helper_connector_duplicate_state
__drm_atomic_helper_connector_reset
__drm_atomic_helper_crtc_destroy_state
__drm_atomic_helper_crtc_duplicate_state
drm_atomic_helper_disable_plane
drm_atomic_helper_legacy_gamma_set
drm_atomic_helper_page_flip
__drm_atomic_helper_plane_destroy_state
drm_atomic_helper_plane_destroy_state
__drm_atomic_helper_plane_duplicate_state
drm_atomic_helper_prepare_planes
drm_atomic_helper_resume
drm_atomic_helper_set_config
drm_atomic_helper_setup_commit
drm_atomic_helper_shutdown
drm_atomic_helper_suspend
drm_atomic_helper_swap_state
drm_atomic_helper_update_legacy_modeset_state
drm_atomic_helper_update_plane
drm_atomic_helper_wait_for_dependencies
drm_atomic_helper_wait_for_fences
drm_atomic_helper_wait_for_flip_done
drm_atomic_state_alloc
drm_atomic_state_default_clear
drm_atomic_state_default_release
__drm_atomic_state_free
drm_atomic_state_init
drm_calc_vbltimestamp_from_scanoutpos
drm_color_lut_extract
drm_compat_ioctl
drm_connector_attach_encoder
drm_connector_cleanup
drm_connector_init
drm_connector_list_iter_begin
drm_connector_list_iter_end
drm_connector_list_iter_next
drm_connector_register
drm_connector_set_path_property
drm_connector_unregister
drm_connector_update_edid_property
drm_crtc_accurate_vblank_count
drm_crtc_add_crc_entry
drm_crtc_arm_vblank_event
drm_crtc_cleanup
__drm_crtc_commit_free
drm_crtc_enable_color_mgmt
drm_crtc_force_disable_all
drm_crtc_from_index
drm_crtc_handle_vblank
drm_crtc_helper_set_config
drm_crtc_helper_set_mode
drm_crtc_init
drm_crtc_init_with_planes
drm_crtc_send_vblank_event
drm_crtc_vblank_count
drm_crtc_vblank_get
drm_crtc_vblank_off
drm_crtc_vblank_on
drm_crtc_vblank_put
drm_cvt_mode
drm_dbg
drm_debugfs_create_files
drm_detect_hdmi_monitor
drm_detect_monitor_audio
drm_dev_alloc
drm_dev_put
drm_dev_register
drm_dev_unregister
drm_dp_atomic_find_vcpi_slots
drm_dp_atomic_release_vcpi_slots
drm_dp_aux_register
drm_dp_aux_unregister
drm_dp_bw_code_to_link_rate
drm_dp_calc_pbn_mode
drm_dp_channel_eq_ok
drm_dp_check_act_status
drm_dp_clock_recovery_ok
drm_dp_dpcd_read
drm_dp_dpcd_read_link_status
drm_dp_dpcd_write
drm_dp_find_vcpi_slots
drm_dp_get_adjust_request_pre_emphasis
drm_dp_get_adjust_request_voltage
drm_dp_link_rate_to_bw_code
drm_dp_link_train_channel_eq_delay
drm_dp_link_train_clock_recovery_delay
drm_dp_mst_allocate_vcpi
drm_dp_mst_deallocate_vcpi
drm_dp_mst_detect_port
drm_dp_mst_get_edid
drm_dp_mst_hpd_irq
drm_dp_mst_reset_vcpi_slots
drm_dp_mst_topology_mgr_destroy
drm_dp_mst_topology_mgr_init
drm_dp_mst_topology_mgr_resume
drm_dp_mst_topology_mgr_set_mst
drm_dp_mst_topology_mgr_suspend
drm_dp_update_payload_part1
drm_dp_update_payload_part2
drm_edid_header_is_valid
drm_edid_is_valid
drm_edid_to_sad
drm_edid_to_speaker_allocation
drm_encoder_cleanup
drm_encoder_init
drm_err
drm_fb_helper_add_one_connector
drm_fb_helper_alloc_fbi
drm_fb_helper_blank
drm_fb_helper_cfb_copyarea
drm_fb_helper_cfb_fillrect
drm_fb_helper_cfb_imageblit
drm_fb_helper_check_var
drm_fb_helper_debug_enter
drm_fb_helper_debug_leave
drm_fb_helper_fill_fix
drm_fb_helper_fill_var
drm_fb_helper_fini
drm_fb_helper_hotplug_event
drm_fb_helper_init
drm_fb_helper_initial_config
drm_fb_helper_ioctl
drm_fb_helper_lastclose
drm_fb_helper_output_poll_changed
drm_fb_helper_pan_display
drm_fb_helper_prepare
drm_fb_helper_remove_one_connector
drm_fb_helper_setcmap
drm_fb_helper_set_par
drm_fb_helper_set_suspend
drm_fb_helper_set_suspend_unlocked
drm_fb_helper_single_add_all_connectors
drm_fb_helper_unregister_fbi
drm_format_plane_cpp
drm_framebuffer_cleanup
drm_framebuffer_init
drm_framebuffer_unregister_private
drm_gem_dmabuf_kmap
drm_gem_dmabuf_kunmap
drm_gem_dmabuf_mmap
drm_gem_dmabuf_release
drm_gem_dmabuf_vmap
drm_gem_dmabuf_vunmap
drm_gem_fb_create_handle
drm_gem_fb_destroy
drm_gem_handle_create
drm_gem_handle_delete
drm_gem_map_attach
drm_gem_map_detach
drm_gem_map_dma_buf
drm_gem_object_init
drm_gem_object_lookup
drm_gem_object_put_unlocked
drm_gem_object_release
drm_gem_prime_export
drm_gem_prime_fd_to_handle
drm_gem_prime_handle_to_fd
drm_gem_prime_import
drm_gem_private_object_init
drm_gem_unmap_dma_buf
drm_get_edid
drm_get_edid_switcheroo
drm_get_format_name
drm_get_max_iomem
drm_global_item_ref
drm_global_item_unref
drm_handle_vblank
drm_hdmi_avi_infoframe_from_display_mode
drm_hdmi_vendor_infoframe_from_display_mode
drm_helper_connector_dpms
drm_helper_disable_unused_functions
drm_helper_hpd_irq_event
drm_helper_mode_fill_fb_struct
drm_helper_probe_single_connector_modes
drm_helper_resume_force_mode
drm_i2c_encoder_detect
drm_i2c_encoder_init
drm_i2c_encoder_mode_fixup
drm_i2c_encoder_restore
drm_i2c_encoder_save
drm_invalid_op
drm_ioctl
drm_irq_install
drm_irq_uninstall
drm_is_current_master
drm_kms_helper_hotplug_event
drm_kms_helper_is_poll_worker
drm_kms_helper_poll_disable
drm_kms_helper_poll_enable
drm_kms_helper_poll_fini
drm_kms_helper_poll_init
drm_match_cea_mode
drm_mm_init
drm_mm_insert_node_in_range
drm_mm_print
drm_mm_remove_node
drm_mm_takedown
drm_mode_config_cleanup
drm_mode_config_init
drm_mode_config_reset
drm_mode_copy
drm_mode_create_dvi_i_properties
drm_mode_create_scaling_mode_property
drm_mode_create_tv_properties
drm_mode_crtc_set_gamma_size
drm_mode_debug_printmodeline
drm_mode_destroy
drm_mode_duplicate
drm_mode_equal
drm_mode_get_hv_timing
drm_mode_is_420_only
drm_mode_legacy_fb_format
drm_mode_object_find
drm_mode_object_put
drm_mode_probed_add
drm_mode_set_crtcinfo
drm_modeset_lock
drm_modeset_lock_all
drm_modeset_lock_all_ctx
drm_mode_set_name
drm_modeset_unlock
drm_modeset_unlock_all
drm_mode_vrefresh
drm_object_attach_property
drm_object_property_set_value
drm_open
drm_plane_cleanup
drm_plane_create_alpha_property
drm_plane_create_color_properties
drm_plane_create_zpos_immutable_property
drm_plane_create_zpos_property
drm_plane_force_disable
drm_plane_init
drm_poll
drm_primary_helper_destroy
drm_primary_helper_funcs
drm_prime_gem_destroy
drm_prime_pages_to_sg
drm_prime_sg_to_page_addr_arrays
drm_printf
__drm_printfn_seq_file
drm_property_add_enum
drm_property_create
drm_property_create_enum
drm_property_create_range
__drm_puts_seq_file
drm_read
drm_release
drm_scdc_read
drm_scdc_write
drm_sched_dependency_optimized
drm_sched_entity_destroy
drm_sched_entity_fini
drm_sched_entity_flush
drm_sched_entity_init
drm_sched_entity_push_job
drm_sched_entity_set_rq
drm_sched_fini
drm_sched_hw_job_reset
drm_sched_init
drm_sched_job_init
drm_sched_job_recovery
drm_send_event_locked
drm_syncobj_create
drm_syncobj_find
drm_syncobj_find_fence
drm_syncobj_free
drm_syncobj_get_fd
drm_syncobj_get_handle
drm_syncobj_replace_fence
drm_universal_plane_init
drm_vblank_init
drm_vma_node_allow
drm_vma_node_is_allowed
drm_vma_node_revoke
dst_release
dummy_dma_ops
dump_stack
__dynamic_dev_dbg
__dynamic_netdev_dbg
__dynamic_pr_debug
elfcorehdr_addr
emergency_restart
enable_irq
errno_to_blk_status
ether_setup
eth_get_headlen
eth_platform_get_mac_address
ethtool_convert_legacy_u32_to_link_mode
ethtool_convert_link_mode_to_legacy_u32
ethtool_intersect_link_masks
ethtool_op_get_link
ethtool_op_get_ts_info
eth_type_trans
eth_validate_addr
eventfd_ctx_fdget
eventfd_ctx_put
eventfd_signal
event_triggers_call
fasync_helper
fc_attach_transport
fc_block_scsi_eh
fc_eh_timed_out
fc_get_event_number
fc_host_post_event
fc_host_post_vendor_event
fc_release_transport
fc_remote_port_add
fc_remote_port_delete
fc_remote_port_rolechg
fc_remove_host
fc_vport_create
fc_vport_terminate
fd_install
fget
filemap_fault
filp_close
filp_open
find_get_pid
find_last_bit
find_next_bit
find_next_zero_bit
find_pid_ns
find_vma
finish_wait
firmware_request_nowarn
fixed_size_llseek
flow_keys_dissector
flush_delayed_work
flush_signals
flush_work
flush_workqueue
force_sig
fortify_panic
fput
free_fib_info
free_irq
free_irq_cpu_rmap
free_netdev
__free_pages
free_pages
free_percpu
from_kgid
from_kuid
fs_bio_set
gcd
generate_random_uuid
generic_end_io_acct
generic_file_llseek
generic_handle_irq
generic_make_request
generic_start_io_acct
genlmsg_put
genl_register_family
genl_unregister_family
genphy_read_status
genphy_restart_aneg
get_device
__get_free_pages
get_gendisk
get_pid_task
get_random_bytes
__get_task_comm
get_task_mm
get_unused_fd_flags
get_user_pages
get_user_pages_remote
get_zeroed_page
gic_pmr_sync
groups_alloc
groups_free
handle_simple_irq
hdmi_avi_infoframe_pack
hdmi_infoframe_pack
hnae3_register_ae_algo
hnae3_register_ae_dev
hnae3_register_client
hnae3_set_client_init_flag
hnae3_unregister_ae_algo
hnae3_unregister_ae_dev
hnae3_unregister_client
hrtimer_cancel
hrtimer_forward
hrtimer_init
hrtimer_start_range_ns
hrtimer_try_to_cancel
__hw_addr_sync_dev
__hw_addr_unsync_dev
hwmon_device_register
hwmon_device_register_with_groups
hwmon_device_register_with_info
hwmon_device_unregister
i2c_add_adapter
i2c_bit_add_bus
i2c_bit_algo
i2c_del_adapter
i2c_new_device
i2c_smbus_read_byte_data
i2c_smbus_write_byte_data
i2c_transfer
i2c_unregister_device
__ib_alloc_cq
ib_alloc_device
ib_alloc_odp_umem
__ib_alloc_pd
__ib_alloc_xrcd
__ib_create_cq
ib_create_qp
ib_create_send_mad
ib_dealloc_device
ib_dealloc_pd
ib_dereg_mr
ib_destroy_cq
ib_destroy_qp
ib_dispatch_event
ib_find_cached_pkey
ib_free_cq
ib_free_send_mad
ib_get_cached_pkey
ib_get_eth_speed
ib_get_gids_from_rdma_hdr
ib_get_rdma_header_version
ib_modify_qp
ib_modify_qp_is_ok
ib_post_send_mad
ib_process_cq_direct
ib_query_pkey
ib_query_port
ib_query_qp
ib_register_device
ib_register_mad_agent
ib_sa_cancel_query
ib_sa_guid_info_rec_query
ib_sa_register_client
ib_sa_unregister_client
ib_sg_to_pages
ib_ud_header_init
ib_ud_header_pack
ib_ud_ip4_csum
ib_umem_copy_from
ib_umem_get
ib_umem_odp_map_dma_pages
ib_umem_odp_unmap_dma_pages
ib_umem_page_count
ib_umem_release
ib_unregister_device
ib_unregister_mad_agent
ib_uverbs_get_ucontext
ida_alloc_range
ida_destroy
ida_free
idr_alloc
idr_alloc_cyclic
idr_alloc_u32
idr_destroy
idr_find
idr_for_each
idr_get_next
idr_get_next_ul
idr_preload
idr_remove
idr_replace
in4_pton
in6_pton
in_egroup_p
__inet6_lookup_established
__inet_lookup_established
in_group_p
init_net
__init_rwsem
init_srcu_struct
init_task
init_timer_key
init_uts_ns
init_wait_entry
__init_waitqueue_head
interval_tree_insert
interval_tree_iter_first
interval_tree_iter_next
interval_tree_remove
int_to_scsilun
invalidate_partition
iomem_resource
iommu_get_domain_for_dev
iommu_iova_to_phys
iommu_map
iommu_unmap
__ioremap
ioremap_cache
io_schedule
io_schedule_timeout
__iounmap
__iowrite32_copy
__iowrite64_copy
ip6_dst_hoplimit
ip_compute_csum
ipmi_create_user
ipmi_destroy_user
ipmi_free_recv_msg
ipmi_poll_interface
ipmi_request_settime
ipmi_set_gets_events
ipmi_set_my_address
ipmi_smi_msg_received
ipmi_unregister_smi
ipmi_validate_addr
ip_route_output_flow
ip_send_check
__ipv6_addr_type
ipv6_ext_hdr
ipv6_find_hdr
ipv6_skip_exthdr
ipv6_stub
irq_cpu_rmap_add
irq_create_mapping
__irq_domain_add
irq_domain_remove
irq_find_mapping
irq_get_irq_data
irq_poll_complete
irq_poll_disable
irq_poll_enable
irq_poll_init
irq_poll_sched
irq_set_affinity_hint
irq_set_affinity_notifier
irq_set_chip_and_handler_name
irq_to_desc
is_acpi_device_node
jiffies
jiffies_64
jiffies_to_msecs
jiffies_to_timespec64
jiffies_to_usecs
kallsyms_lookup_name
kasprintf
kernel_recvmsg
kernel_sendmsg
kernel_setsockopt
kfree
kfree_call_rcu
kfree_const
kfree_skb
kgdb_active
kgdb_breakpoint
kill_fasync
kimage_voffset
__kmalloc
kmalloc_caches
__kmalloc_node
kmalloc_order_trace
kmem_cache_alloc
kmem_cache_alloc_node
kmem_cache_alloc_node_trace
kmem_cache_alloc_trace
kmem_cache_create
kmem_cache_create_usercopy
kmem_cache_destroy
kmem_cache_free
kmem_cache_shrink
kmemdup
kobject_add
kobject_create_and_add
kobject_del
kobject_get
kobject_init
kobject_init_and_add
kobject_put
kobject_set_name
kobject_uevent
kobject_uevent_env
krealloc
kset_create_and_add
kset_find_obj
kset_register
kset_unregister
ksize
kstrdup
kstrdup_const
kstrndup
kstrtobool
kstrtobool_from_user
kstrtoint
kstrtoint_from_user
kstrtoll
kstrtoll_from_user
kstrtou16
kstrtouint
kstrtouint_from_user
kstrtoul_from_user
kstrtoull
kstrtoull_from_user
kthread_bind
kthread_create_on_node
kthread_park
kthread_should_stop
kthread_stop
kthread_unpark
ktime_get
ktime_get_coarse_real_ts64
ktime_get_raw
ktime_get_raw_ts64
ktime_get_real_seconds
ktime_get_real_ts64
ktime_get_seconds
ktime_get_ts64
ktime_get_with_offset
kvasprintf
kvfree
kvmalloc_node
kzfree
led_classdev_resume
led_classdev_suspend
led_classdev_unregister
__list_add_valid
__list_del_entry_valid
llist_add_batch
__ll_sc_atomic64_add
__ll_sc_atomic64_add_return
__ll_sc_atomic64_andnot
__ll_sc_atomic64_fetch_add
__ll_sc_atomic64_fetch_andnot
__ll_sc_atomic64_fetch_andnot_release
__ll_sc_atomic64_fetch_or
__ll_sc_atomic64_fetch_or_acquire
__ll_sc_atomic64_fetch_xor
__ll_sc_atomic64_or
__ll_sc_atomic64_sub
__ll_sc_atomic64_sub_return
__ll_sc_atomic_add
__ll_sc_atomic_add_return
__ll_sc_atomic_add_return_acquire
__ll_sc_atomic_sub
__ll_sc_atomic_sub_return
__ll_sc_atomic_sub_return_release
__ll_sc___cmpxchg_case_acq_4
__ll_sc___cmpxchg_case_mb_4
__ll_sc___cmpxchg_case_mb_8
__local_bh_enable_ip
__lock_page
lock_page_memcg
lockref_get
lock_sock_nested
logic_inw
logic_outw
make_kgid
make_kuid
mark_page_accessed
match_strdup
match_string
match_token
_mcount
mdev_dev
mdev_from_dev
mdev_get_drvdata
mdev_parent_dev
mdev_register_device
mdev_register_driver
mdev_set_drvdata
mdev_unregister_device
mdev_unregister_driver
mdio45_probe
mdiobus_alloc_size
mdiobus_free
mdiobus_get_phy
mdiobus_read
__mdiobus_register
mdiobus_unregister
mdiobus_write
mdio_mii_ioctl
memchr
memchr_inv
memcmp
memcpy
__memcpy_fromio
__memcpy_toio
memdup_user
memdup_user_nul
memmove
memory_read_from_buffer
memparse
mempool_alloc
mempool_alloc_slab
mempool_create
mempool_create_node
mempool_destroy
mempool_free
mempool_free_slab
mempool_kfree
mempool_kmalloc
memscan
mem_section
memset
__memset_io
memstart_addr
memzero_explicit
metadata_dst_alloc
misc_deregister
misc_register
mlxfw_firmware_flash
mmput
__mmu_notifier_register
mmu_notifier_register
mmu_notifier_unregister
mmu_notifier_unregister_no_release
mod_delayed_work_on
mod_timer
mod_timer_pending
__module_get
module_layout
module_put
module_refcount
__msecs_to_jiffies
msleep
msleep_interruptible
__mutex_init
mutex_lock
mutex_lock_interruptible
mutex_lock_killable
mutex_trylock
mutex_unlock
__napi_alloc_skb
napi_complete_done
napi_consume_skb
napi_disable
napi_gro_flush
napi_gro_receive
napi_hash_del
__napi_schedule
__napi_schedule_irqoff
napi_schedule_prep
__ndelay
ndo_dflt_bridge_getlink
ndo_dflt_fdb_add
neigh_destroy
__neigh_event_send
neigh_lookup
netdev_alloc_frag
__netdev_alloc_skb
netdev_bind_sb_channel_queue
netdev_crit
netdev_err
netdev_features_change
netdev_info
netdev_lower_get_next
netdev_master_upper_dev_get
netdev_master_upper_dev_get_rcu
netdev_notice
netdev_printk
netdev_reset_tc
netdev_rss_key_fill
netdev_rx_handler_register
netdev_rx_handler_unregister
netdev_set_num_tc
netdev_set_sb_channel
netdev_set_tc_queue
netdev_unbind_sb_channel
netdev_update_features
netdev_walk_all_upper_dev_rcu
netdev_warn
netif_carrier_off
netif_carrier_on
netif_device_attach
netif_device_detach
netif_get_num_default_rss_queues
netif_napi_add
netif_napi_del
netif_receive_skb
netif_rx
netif_schedule_queue
netif_set_real_num_rx_queues
netif_set_real_num_tx_queues
netif_set_xps_queue
netif_tx_stop_all_queues
netif_tx_wake_queue
netlink_ack
netlink_broadcast
__netlink_kernel_create
netlink_kernel_release
netlink_unicast
net_ratelimit
nla_find
nla_parse
nla_put
__nlmsg_put
node_data
__node_distance
node_states
node_to_cpumask_map
no_llseek
noop_llseek
nr_cpu_ids
nr_node_ids
nsecs_to_jiffies
ns_to_timespec
ns_to_timespec64
ns_to_timeval
numa_node
nvme_alloc_request
nvme_cancel_request
nvme_change_ctrl_state
nvme_cleanup_cmd
nvme_complete_async_event
nvme_complete_rq
nvme_disable_ctrl
nvme_enable_ctrl
nvme_fc_register_localport
nvme_fc_register_remoteport
nvme_fc_set_remoteport_devloss
nvme_fc_unregister_localport
nvme_fc_unregister_remoteport
nvme_init_ctrl
nvme_init_identify
nvme_io_timeout
nvme_kill_queues
nvme_remove_namespaces
nvme_reset_ctrl
nvme_reset_ctrl_sync
nvme_set_queue_count
nvme_setup_cmd
nvme_shutdown_ctrl
nvme_start_ctrl
nvme_start_freeze
nvme_start_queues
nvme_stop_ctrl
nvme_stop_queues
nvme_submit_sync_cmd
nvmet_fc_rcv_fcp_abort
nvmet_fc_rcv_fcp_req
nvmet_fc_rcv_ls_req
nvmet_fc_register_targetport
nvmet_fc_unregister_targetport
nvme_unfreeze
nvme_uninit_ctrl
nvme_wait_freeze
nvme_wait_freeze_timeout
nvme_wq
of_led_classdev_register
on_each_cpu
orderly_poweroff
out_of_line_wait_on_bit
override_creds
__page_file_index
__page_frag_cache_drain
page_frag_free
__page_mapcount
page_mapped
page_pool_alloc_pages
page_pool_create
page_pool_destroy
__page_pool_put_page
pagevec_lookup_range
pagevec_lookup_range_tag
__pagevec_release
panic
panic_notifier_list
param_array_ops
param_get_int
param_ops_bool
param_ops_byte
param_ops_charp
param_ops_int
param_ops_long
param_ops_short
param_ops_string
param_ops_uint
param_ops_ullong
param_ops_ulong
param_ops_ushort
param_set_bool
param_set_int
pci_alloc_irq_vectors_affinity
pci_assign_unassigned_bus_resources
pcibios_resource_to_bus
pci_bus_read_config_dword
pci_bus_resource_n
pci_bus_type
pci_cfg_access_lock
pci_cfg_access_unlock
pci_check_and_mask_intx
pci_choose_state
pci_cleanup_aer_uncorrect_error_status
pci_clear_master
pci_clear_mwi
pci_d3cold_disable
pci_dev_driver
pci_dev_get
pci_device_is_present
pci_dev_present
pci_dev_put
pci_disable_device
pci_disable_link_state
pci_disable_msi
pci_disable_msix
pci_disable_pcie_error_reporting
pci_disable_rom
pci_disable_sriov
pcie_bandwidth_available
pcie_capability_clear_and_set_word
pcie_capability_read_dword
pcie_capability_read_word
pcie_capability_write_word
pcie_flr
pcie_get_speed_cap
pcie_get_width_cap
pci_enable_atomic_ops_to_root
pci_enable_device
pci_enable_device_mem
pci_enable_msi
pci_enable_msix_range
pci_enable_pcie_error_reporting
pci_enable_rom
pci_enable_sriov
pci_enable_wake
pcie_print_link_status
pcie_relaxed_ordering_enabled
pcie_set_readrq
pci_find_capability
pci_find_ext_capability
pci_free_irq
pci_free_irq_vectors
pci_get_class
pci_get_device
pci_get_domain_bus_and_slot
pci_get_slot
pci_ignore_hotplug
pci_intx
pci_iomap
pci_ioremap_bar
pci_irq_get_affinity
pci_irq_vector
pci_map_rom
pci_match_id
pcim_enable_device
pcim_iomap
pcim_iomap_regions
pcim_iomap_table
pcim_iounmap
pci_msi_mask_irq
pci_msi_unmask_irq
pci_num_vf
pci_platform_rom
pci_prepare_to_sleep
pci_read_config_byte
pci_read_config_dword
pci_read_config_word
pci_read_vpd
__pci_register_driver
pci_release_regions
pci_release_resource
pci_release_selected_regions
pci_request_irq
pci_request_regions
pci_request_selected_regions
pci_rescan_bus
pci_resize_resource
pci_restore_state
pci_save_state
pci_select_bars
pci_set_master
pci_set_mwi
pci_set_power_state
pci_sriov_configure_simple
pci_sriov_get_totalvfs
pci_sriov_set_totalvfs
pci_stop_and_remove_bus_device
pci_stop_and_remove_bus_device_locked
pci_try_set_mwi
pci_unmap_rom
pci_unregister_driver
pci_vfs_assigned
pci_vpd_find_info_keyword
pci_vpd_find_tag
pci_wait_for_pending_transaction
pci_wake_from_d3
pci_write_config_byte
pci_write_config_dword
pci_write_config_word
pcix_set_mmrbc
PDE_DATA
__per_cpu_offset
perf_trace_buf_alloc
perf_trace_run_bpf_submit
pfn_valid
phy_attached_info
phy_connect
phy_connect_direct
phy_disconnect
phy_ethtool_ksettings_get
phy_ethtool_ksettings_set
phy_loopback
phy_mii_ioctl
phy_resume
phy_start
phy_start_aneg
phy_stop
phy_suspend
pid_task
pid_vnr
pm_power_off
pm_runtime_allow
__pm_runtime_disable
pm_runtime_enable
pm_runtime_forbid
__pm_runtime_idle
__pm_runtime_resume
pm_runtime_set_autosuspend_delay
__pm_runtime_set_status
__pm_runtime_suspend
__pm_runtime_use_autosuspend
pm_schedule_suspend
power_supply_is_system_supplied
prandom_bytes
prandom_u32
prepare_creds
prepare_to_wait
prepare_to_wait_event
prepare_to_wait_exclusive
print_hex_dump
printk
__printk_ratelimit
print_stack_trace
proc_create_data
proc_mkdir
__pskb_copy_fclone
pskb_expand_head
__pskb_pull_tail
___pskb_trim
ptp_clock_event
ptp_clock_index
ptp_clock_register
ptp_clock_unregister
ptp_find_pin
__put_cred
put_device
put_disk
__put_page
__put_task_struct
put_unused_fd
qed_get_eth_ops
qed_put_eth_ops
queue_delayed_work_on
queued_read_lock_slowpath
queued_spin_lock_slowpath
queued_write_lock_slowpath
queue_work_on
radix_tree_delete
radix_tree_gang_lookup
__radix_tree_insert
radix_tree_lookup
radix_tree_tagged
raid_class_attach
raid_class_release
___ratelimit
raw_notifier_call_chain
raw_notifier_chain_register
raw_notifier_chain_unregister
rb_erase
__rb_erase_color
rb_first
rb_first_postorder
__rb_insert_augmented
rb_insert_color
rb_next
rb_next_postorder
rb_replace_node
rbt_ib_umem_for_each_in_range
rbt_ib_umem_lookup
rcu_barrier
rdma_create_ah
rdma_destroy_ah
rdma_is_zero_gid
rdma_port_get_link_layer
rdma_query_ah
rdma_query_gid
rdma_restrack_get
rdma_restrack_put
rdma_roce_rescan_device
read_cache_pages
recalc_sigpending
refcount_dec_and_mutex_lock
refcount_dec_and_test_checked
refcount_dec_checked
refcount_inc_checked
refcount_inc_not_zero_checked
register_acpi_notifier
register_blkdev
__register_chrdev
register_chrdev_region
register_fib_notifier
register_inet6addr_notifier
register_inetaddr_notifier
register_netdev
register_netdevice_notifier
register_netevent_notifier
register_reboot_notifier
release_firmware
release_pages
__release_region
release_sock
remap_pfn_range
remove_conflicting_framebuffers
remove_proc_entry
remove_wait_queue
request_firmware
request_firmware_direct
request_firmware_nowait
__request_module
__request_region
request_threaded_irq
reservation_object_add_excl_fence
reservation_object_add_shared_fence
reservation_object_get_fences_rcu
reservation_object_reserve_shared
reservation_object_wait_timeout_rcu
reservation_ww_class
reset_devices
revert_creds
rhashtable_destroy
rhashtable_free_and_destroy
rhashtable_init
rhashtable_insert_slow
rhashtable_walk_enter
rhashtable_walk_exit
rhashtable_walk_next
rhashtable_walk_start_check
rhashtable_walk_stop
rhltable_init
rht_bucket_nested
rht_bucket_nested_insert
round_jiffies
round_jiffies_relative
rps_may_expire_flow
rtc_time64_to_tm
rtnl_is_locked
rtnl_lock
rtnl_trylock
rtnl_unlock
sas_attach_transport
sas_disable_tlr
sas_enable_tlr
sas_end_device_alloc
sas_expander_alloc
sas_is_tlr_enabled
sas_phy_add
sas_phy_alloc
sas_phy_free
sas_port_add
sas_port_add_phy
sas_port_alloc_num
sas_port_delete
sas_port_delete_phy
sas_port_free
sas_read_port_mode_page
sas_release_transport
sas_remove_host
sas_rphy_add
save_stack_trace
save_stack_trace_tsk
sbitmap_queue_clear
__sbitmap_queue_get
sched_clock
sched_setscheduler
schedule
schedule_hrtimeout
schedule_hrtimeout_range
schedule_timeout
schedule_timeout_interruptible
schedule_timeout_uninterruptible
scmd_printk
scnprintf
scsi_add_device
scsi_add_host_with_dma
scsi_block_requests
scsi_build_sense_buffer
scsi_change_queue_depth
scsi_device_get
scsi_device_lookup
scsi_device_put
scsi_device_set_state
scsi_device_type
scsi_dma_map
scsi_dma_unmap
__scsi_execute
scsi_get_vpd_page
scsi_host_alloc
scsi_host_busy
scsi_host_get
scsi_host_lookup
scsi_host_put
scsi_internal_device_block_nowait
scsi_internal_device_unblock_nowait
scsi_is_fc_rport
scsi_is_host_device
scsi_is_sdev_device
__scsi_iterate_devices
scsilun_to_int
scsi_normalize_sense
scsi_print_command
scsi_register_driver
scsi_remove_device
scsi_remove_host
scsi_remove_target
scsi_sanitize_inquiry_string
scsi_scan_host
scsi_unblock_requests
sdev_prefix_printk
secpath_dup
security_d_instantiate
send_sig
seq_lseek
seq_open
seq_printf
seq_putc
seq_puts
seq_read
seq_release
seq_write
set_cpus_allowed_ptr
set_current_groups
set_device_ro
set_disk_ro
set_freezable
set_normalized_timespec64
set_page_dirty
set_page_dirty_lock
set_user_nice
sg_alloc_table_from_pages
sg_copy_from_buffer
sg_copy_to_buffer
sg_free_table
sg_init_table
sg_miter_next
sg_miter_start
sg_miter_stop
sg_next
sigprocmask
si_meminfo
simple_attr_open
simple_attr_read
simple_attr_release
simple_attr_write
simple_open
simple_read_from_buffer
simple_strtol
simple_strtoul
simple_strtoull
simple_write_to_buffer
single_open
single_release
skb_add_rx_frag
skb_checksum
skb_checksum_help
skb_clone
skb_clone_tx_timestamp
skb_copy
skb_copy_bits
skb_copy_expand
skb_dequeue
__skb_flow_dissect
__skb_get_hash
__skb_gso_segment
skb_gso_validate_mac_len
__skb_pad
skb_pull
skb_push
skb_put
skb_queue_purge
skb_queue_tail
skb_realloc_headroom
skb_store_bits
skb_trim
skb_tstamp_tx
skb_vlan_pop
sk_free
smp_call_function_many
smp_call_function_single
snprintf
sock_create_kern
sock_edemux
sock_queue_err_skb
sock_release
softnet_data
sort
sprintf
srcu_barrier
__srcu_read_lock
__srcu_read_unlock
sscanf
__stack_chk_fail
__stack_chk_guard
starget_for_each_device
strcasecmp
strcat
strchr
strcmp
strcpy
strcspn
strim
strlcat
strlcpy
strlen
strncasecmp
strncat
strncmp
strncpy
strncpy_from_user
strnlen
strnstr
strpbrk
strrchr
strsep
strspn
strstr
submit_bio
__sw_hweight32
__sw_hweight64
__sw_hweight8
swiotlb_nr_tbl
switchdev_port_same_parent_id
__symbol_put
sync_file_create
synchronize_irq
synchronize_net
synchronize_sched
synchronize_srcu
sysfs_add_file_to_group
sysfs_create_bin_file
sysfs_create_file_ns
sysfs_create_group
sysfs_remove_bin_file
sysfs_remove_file_from_group
sysfs_remove_file_ns
sysfs_remove_group
sysfs_streq
system_state
system_unbound_wq
system_wq
sys_tz
task_active_pid_ns
tasklet_init
tasklet_kill
__tasklet_schedule
__task_pid_nr_ns
tcf_block_cb_register
tcf_block_cb_unregister
tcp_gro_complete
tcp_hashinfo
tc_setup_cb_egdev_register
tc_setup_cb_egdev_unregister
time64_to_tm
timecounter_cyc2time
timecounter_init
timecounter_read
tls_get_record
tls_validate_xmit_skb
to_drm_sched_fence
trace_define_field
trace_event_buffer_commit
trace_event_buffer_reserve
trace_event_ignore_this_pid
trace_event_raw_init
trace_event_reg
trace_handle_return
__tracepoint_dma_fence_emit
__tracepoint_xdp_exception
trace_print_array_seq
trace_print_flags_seq
trace_raw_output_prep
trace_seq_printf
trace_seq_putc
try_module_get
try_wait_for_completion
ttm_bo_add_to_lru
ttm_bo_clean_mm
ttm_bo_del_sub_from_lru
ttm_bo_device_init
ttm_bo_device_release
ttm_bo_dma_acc_size
ttm_bo_eviction_valuable
ttm_bo_evict_mm
ttm_bo_global_init
ttm_bo_global_release
ttm_bo_init
ttm_bo_init_mm
ttm_bo_init_reserved
ttm_bo_kmap
ttm_bo_kunmap
ttm_bo_lock_delayed_workqueue
ttm_bo_manager_func
ttm_bo_mem_put
ttm_bo_mem_space
ttm_bo_mmap
ttm_bo_move_accel_cleanup
ttm_bo_move_memcpy
ttm_bo_move_to_lru_tail
ttm_bo_move_ttm
ttm_bo_pipeline_move
ttm_bo_put
ttm_bo_unlock_delayed_workqueue
ttm_bo_validate
ttm_bo_wait
ttm_dma_page_alloc_debugfs
ttm_dma_populate
ttm_dma_tt_fini
ttm_dma_tt_init
ttm_dma_unpopulate
ttm_eu_backoff_reservation
ttm_eu_fence_buffer_objects
ttm_eu_reserve_buffers
ttm_fbdev_mmap
ttm_mem_global_init
ttm_mem_global_release
ttm_page_alloc_debugfs
ttm_pool_populate
ttm_pool_unpopulate
ttm_populate_and_map_pages
ttm_sg_tt_init
ttm_tt_bind
ttm_tt_set_placement_caching
ttm_unmap_and_unpopulate_pages
__udelay
udp4_hwcsum
uio_event_notify
__uio_register_device
uio_unregister_device
unlock_page
unlock_page_memcg
unmap_mapping_range
unregister_acpi_notifier
unregister_blkdev
__unregister_chrdev
unregister_chrdev_region
unregister_fib_notifier
unregister_inet6addr_notifier
unregister_inetaddr_notifier
unregister_netdev
unregister_netdevice_notifier
unregister_netevent_notifier
unregister_reboot_notifier
unuse_mm
up
up_read
up_write
__usecs_to_jiffies
use_mm
usleep_range
_uverbs_alloc
uverbs_copy_to
uverbs_destroy_def_handler
uverbs_fd_class
uverbs_get_flags32
uverbs_get_flags64
uverbs_idr_class
vfree
vga_client_register
vlan_dev_real_dev
vlan_dev_vlan_id
vlan_dev_vlan_proto
vmalloc
__vmalloc
vmalloc_node
vmalloc_to_page
vmap
vm_insert_page
vm_mmap
vm_munmap
vprintk
vscnprintf
vsnprintf
vsprintf
vunmap
vzalloc
vzalloc_node
wait_for_completion
wait_for_completion_interruptible
wait_for_completion_interruptible_timeout
wait_for_completion_io_timeout
wait_for_completion_killable
wait_for_completion_timeout
wait_on_page_bit
__wake_up
wake_up_bit
__wake_up_locked
wake_up_process
__warn_printk
work_busy
write_cache_pages
ww_mutex_lock
ww_mutex_lock_interruptible
ww_mutex_unlock
xdp_do_flush_map
xdp_do_redirect
xdp_return_frame
xdp_return_frame_rx_napi
xdp_rxq_info_is_reg
xdp_rxq_info_reg
xdp_rxq_info_reg_mem_model
xdp_rxq_info_unreg
xdp_rxq_info_unused
xfrm_replay_seqhi
xz_dec_end
xz_dec_init
xz_dec_run
yield
zap_vma_ptes
zlib_inflate
zlib_inflateEnd
zlib_inflateInit2
zlib_inflate_workspacesize
附2:x86 平台 KABI 白名单列表初稿(2228个)
acpi_bus_get_device
acpi_bus_register_driver
acpi_bus_unregister_driver
acpi_check_dsm
acpi_dev_found
acpi_disabled
acpi_dma_configure
acpi_evaluate_dsm
acpi_evaluate_integer
acpi_evaluate_object
acpi_format_exception
acpi_gbl_FADT
acpi_get_devices
acpi_get_handle
acpi_get_name
acpi_get_table
acpi_gsi_to_irq
acpi_handle_printk
acpi_has_method
acpi_install_notify_handler
acpi_lid_open
acpi_os_map_memory
acpi_os_unmap_memory
acpi_register_gsi
acpi_remove_notify_handler
acpi_unregister_gsi
acpi_video_get_edid
acpi_walk_namespace
address_space_init_once
add_timer
add_wait_queue
add_wait_queue_exclusive
admin_timeout
alloc_chrdev_region
alloc_cpumask_var
alloc_cpu_rmap
__alloc_disk_node
alloc_etherdev_mqs
alloc_netdev_mqs
alloc_pages_current
__alloc_pages_nodemask
__alloc_percpu
__alloc_skb
__alloc_workqueue_key
anon_inode_getfile
apic
arch_dma_alloc_attrs
arch_io_free_memtype_wc
arch_io_reserve_memtype_wc
arch_phys_wc_add
arch_phys_wc_del
arch_wb_cache_pmem
arp_tbl
async_schedule
_atomic_dec_and_lock
atomic_notifier_call_chain
atomic_notifier_chain_register
atomic_notifier_chain_unregister
attribute_container_find_class_device
autoremove_wake_function
backlight_device_register
backlight_device_unregister
backlight_force_update
bdevname
bdev_read_only
bdget_disk
_bin2bcd
bio_add_page
bio_alloc_bioset
bio_clone_fast
bio_endio
bio_free_pages
bio_init
bio_put
bioset_exit
bioset_init
__bitmap_and
__bitmap_andnot
__bitmap_clear
__bitmap_complement
__bitmap_equal
bitmap_find_free_region
bitmap_find_next_zero_area_off
__bitmap_intersects
__bitmap_or
__bitmap_parse
bitmap_parselist
bitmap_print_to_pagebuf
bitmap_release_region
__bitmap_set
__bitmap_shift_left
__bitmap_shift_right
__bitmap_subset
__bitmap_weight
__bitmap_xor
bitmap_zalloc
bit_wait
blk_alloc_queue
blk_check_plugged
blk_cleanup_queue
blkdev_get_by_path
blkdev_issue_discard
blkdev_issue_write_same
blkdev_issue_zeroout
blkdev_put
blk_execute_rq
blk_execute_rq_nowait
blk_finish_plug
blk_get_queue
blk_get_request
blk_init_tags
blk_mq_alloc_tag_set
blk_mq_complete_request
blk_mq_end_request
blk_mq_free_request
blk_mq_free_tag_set
blk_mq_init_queue
blk_mq_map_queues
blk_mq_pci_map_queues
blk_mq_quiesce_queue
blk_mq_run_hw_queues
blk_mq_start_request
blk_mq_tagset_busy_iter
blk_mq_tag_to_rq
blk_mq_unique_tag
blk_mq_unquiesce_queue
blk_mq_update_nr_hw_queues
blk_put_queue
blk_put_request
blk_queue_bounce_limit
blk_queue_dma_alignment
blk_queue_flag_clear
blk_queue_flag_set
blk_queue_free_tags
blk_queue_init_tags
blk_queue_io_min
blk_queue_io_opt
blk_queue_logical_block_size
blk_queue_make_request
blk_queue_max_discard_sectors
blk_queue_max_hw_sectors
blk_queue_max_segments
blk_queue_max_segment_size
blk_queue_max_write_same_sectors
blk_queue_physical_block_size
blk_queue_rq_timeout
blk_queue_segment_boundary
blk_queue_split
blk_queue_stack_limits
blk_queue_update_dma_alignment
blk_queue_virt_boundary
blk_queue_write_cache
blk_rq_append_bio
blk_rq_count_integrity_sg
blk_rq_map_integrity_sg
blk_rq_map_kern
blk_rq_map_sg
blk_rq_map_user_iov
blk_rq_unmap_user
blk_set_stacking_limits
blk_start_plug
blk_status_to_errno
blk_verify_command
blocking_notifier_call_chain
blocking_notifier_chain_register
blocking_notifier_chain_unregister
boot_cpu_data
bpf_prog_add
bpf_prog_inc
bpf_prog_put
bpf_trace_run1
bpf_trace_run2
bpf_trace_run3
bpf_trace_run5
bpf_warn_invalid_xdp_action
bsg_job_done
btree_destroy
btree_geo32
btree_geo64
btree_get_prev
btree_init
btree_insert
btree_last
btree_lookup
btree_remove
btree_update
build_skb
bus_find_device_by_name
__cachemode2pte_tbl
call_netdevice_notifiers
call_rcu_sched
call_usermodehelper
cancel_delayed_work
cancel_delayed_work_sync
cancel_work_sync
capable
cdev_add
cdev_del
cdev_device_add
cdev_device_del
cdev_init
__chash_table_copy_in
__chash_table_copy_out
__check_object_size
__class_create
class_create_file_ns
class_destroy
__class_register
class_remove_file_ns
class_unregister
_cleanup_srcu_struct
clear_user
clk_get_rate
cm_class
cnic_register_driver
cnic_unregister_driver
commit_creds
compat_alloc_user_space
complete
complete_all
complete_and_exit
completion_done
component_add
component_del
_cond_resched
configfs_register_subsystem
configfs_remove_default_groups
configfs_unregister_subsystem
config_group_init
config_group_init_type_name
config_item_put
console_lock
console_unlock
__const_udelay
consume_skb
_copy_from_user
_copy_to_user
copy_user_enhanced_fast_string
copy_user_generic_string
copy_user_generic_unrolled
cpu_bit_bitmap
cpu_core_map
cpufreq_get
cpufreq_quick_get
__cpuhp_remove_state
__cpuhp_setup_state
cpu_info
cpu_khz
cpumask_local_spread
cpumask_next
cpumask_next_and
cpu_number
__cpu_online_mask
__cpu_possible_mask
__cpu_present_mask
cpu_sibling_map
cpus_read_lock
cpus_read_unlock
crc32c
crc32_le
crc8
crc8_populate_msb
crc_t10dif
crypto_ahash_digest
crypto_ahash_final
crypto_ahash_setkey
crypto_alloc_ahash
crypto_destroy_tfm
crypto_register_shash
crypto_unregister_shash
csum_ipv6_magic
csum_partial
_ctype
current_task
dca3_get_tag
dca_add_requester
dca_register_notify
dca_remove_requester
dca_unregister_notify
dcb_getapp
dcb_ieee_delapp
dcb_ieee_getapp_mask
dcb_ieee_setapp
dcbnl_cee_notify
dcbnl_ieee_notify
dcb_setapp
debugfs_create_atomic_t
debugfs_create_dir
debugfs_create_file
debugfs_create_u32
debugfs_create_u64
debugfs_create_u8
debugfs_lookup
debugfs_remove
__default_kernel_pte_mask
default_llseek
default_wake_function
__delay
delayed_work_timer_fn
del_gendisk
del_timer
del_timer_sync
destroy_workqueue
dev_add_pack
dev_addr_add
dev_addr_del
dev_base_lock
dev_close
dev_driver_string
_dev_err
__dev_get_by_index
dev_get_by_index
dev_get_by_index_rcu
dev_get_by_name
dev_get_iflink
dev_get_stats
device_add_disk
device_create
device_create_file
device_destroy
device_initialize
device_link_add
device_release_driver
device_remove_file
device_reprobe
device_set_wakeup_capable
device_set_wakeup_enable
_dev_info
__dev_kfree_skb_any
__dev_kfree_skb_irq
devlink_alloc
devlink_free
devlink_param_driverinit_value_get
devlink_param_driverinit_value_set
devlink_params_register
devlink_params_unregister
devlink_param_value_changed
devlink_port_attrs_set
devlink_port_register
devlink_port_type_clear
devlink_port_type_ib_set
devlink_port_unregister
devlink_region_create
devlink_region_destroy
devlink_region_shapshot_id_get
devlink_region_snapshot_create
devlink_register
devlink_unregister
devmap_managed_key
dev_mc_add
dev_mc_add_excl
dev_mc_del
devm_free_irq
devm_hwmon_device_register_with_groups
devm_ioremap
devm_iounmap
devm_kfree
devm_kmalloc
devm_kmemdup
devm_request_threaded_irq
_dev_notice
dev_printk
dev_queue_xmit
__dev_remove_pack
dev_remove_pack
dev_set_mac_address
dev_set_mtu
dev_set_name
dev_set_promiscuity
dev_trans_start
dev_uc_add
dev_uc_add_excl
dev_uc_del
_dev_warn
disable_irq
disable_irq_nosync
dma_fence_add_callback
dma_fence_array_create
dma_fence_context_alloc
dma_fence_free
dma_fence_get_status
dma_fence_init
dma_fence_release
dma_fence_signal
dma_fence_signal_locked
dma_fence_wait_any_timeout
dma_fence_wait_timeout
dma_get_required_mask
dmam_alloc_coherent
dmam_free_coherent
dma_ops
dma_pool_alloc
dma_pool_create
dma_pool_destroy
dma_pool_free
dmi_check_system
dmi_get_system_info
dmi_match
__do_once_done
__do_once_start
do_wait_intr
down
downgrade_write
down_interruptible
down_read
down_read_trylock
down_timeout
down_trylock
down_write
down_write_killable
down_write_trylock
dput
dql_completed
dql_reset
drain_workqueue
driver_create_file
driver_for_each_device
driver_remove_file
drm_add_edid_modes
drm_add_modes_noedid
drm_atomic_add_affected_connectors
drm_atomic_add_affected_planes
drm_atomic_commit
drm_atomic_get_connector_state
drm_atomic_get_crtc_state
drm_atomic_get_plane_state
drm_atomic_helper_check
drm_atomic_helper_check_modeset
drm_atomic_helper_check_planes
drm_atomic_helper_check_plane_state
drm_atomic_helper_cleanup_planes
drm_atomic_helper_commit
drm_atomic_helper_commit_cleanup_done
drm_atomic_helper_commit_hw_done
__drm_atomic_helper_connector_destroy_state
drm_atomic_helper_connector_destroy_state
__drm_atomic_helper_connector_duplicate_state
__drm_atomic_helper_connector_reset
__drm_atomic_helper_crtc_destroy_state
__drm_atomic_helper_crtc_duplicate_state
drm_atomic_helper_disable_plane
drm_atomic_helper_legacy_gamma_set
drm_atomic_helper_page_flip
__drm_atomic_helper_plane_destroy_state
drm_atomic_helper_plane_destroy_state
__drm_atomic_helper_plane_duplicate_state
drm_atomic_helper_prepare_planes
drm_atomic_helper_resume
drm_atomic_helper_set_config
drm_atomic_helper_setup_commit
drm_atomic_helper_shutdown
drm_atomic_helper_suspend
drm_atomic_helper_swap_state
drm_atomic_helper_update_legacy_modeset_state
drm_atomic_helper_update_plane
drm_atomic_helper_wait_for_dependencies
drm_atomic_helper_wait_for_fences
drm_atomic_helper_wait_for_flip_done
drm_atomic_state_alloc
drm_atomic_state_default_clear
drm_atomic_state_default_release
__drm_atomic_state_free
drm_atomic_state_init
drm_calc_vbltimestamp_from_scanoutpos
drm_color_lut_extract
drm_compat_ioctl
drm_connector_attach_encoder
drm_connector_cleanup
drm_connector_init
drm_connector_list_iter_begin
drm_connector_list_iter_end
drm_connector_list_iter_next
drm_connector_register
drm_connector_set_path_property
drm_connector_unregister
drm_connector_update_edid_property
drm_crtc_accurate_vblank_count
drm_crtc_add_crc_entry
drm_crtc_arm_vblank_event
drm_crtc_cleanup
__drm_crtc_commit_free
drm_crtc_enable_color_mgmt
drm_crtc_force_disable_all
drm_crtc_from_index
drm_crtc_handle_vblank
drm_crtc_helper_set_config
drm_crtc_helper_set_mode
drm_crtc_init
drm_crtc_init_with_planes
drm_crtc_send_vblank_event
drm_crtc_vblank_count
drm_crtc_vblank_get
drm_crtc_vblank_off
drm_crtc_vblank_on
drm_crtc_vblank_put
drm_cvt_mode
drm_dbg
drm_debug
drm_debugfs_create_files
drm_detect_hdmi_monitor
drm_detect_monitor_audio
drm_dev_alloc
drm_dev_put
drm_dev_register
drm_dev_unref
drm_dev_unregister
drm_dp_atomic_find_vcpi_slots
drm_dp_atomic_release_vcpi_slots
drm_dp_aux_register
drm_dp_aux_unregister
drm_dp_bw_code_to_link_rate
drm_dp_calc_pbn_mode
drm_dp_channel_eq_ok
drm_dp_check_act_status
drm_dp_clock_recovery_ok
drm_dp_dpcd_read
drm_dp_dpcd_read_link_status
drm_dp_dpcd_write
drm_dp_find_vcpi_slots
drm_dp_get_adjust_request_pre_emphasis
drm_dp_get_adjust_request_voltage
drm_dp_link_rate_to_bw_code
drm_dp_link_train_channel_eq_delay
drm_dp_link_train_clock_recovery_delay
drm_dp_mst_allocate_vcpi
drm_dp_mst_deallocate_vcpi
drm_dp_mst_detect_port
drm_dp_mst_get_edid
drm_dp_mst_hpd_irq
drm_dp_mst_reset_vcpi_slots
drm_dp_mst_topology_mgr_destroy
drm_dp_mst_topology_mgr_init
drm_dp_mst_topology_mgr_resume
drm_dp_mst_topology_mgr_set_mst
drm_dp_mst_topology_mgr_suspend
drm_dp_update_payload_part1
drm_dp_update_payload_part2
drm_edid_header_is_valid
drm_edid_is_valid
drm_edid_to_sad
drm_edid_to_speaker_allocation
drm_encoder_cleanup
drm_encoder_init
drm_err
drm_fb_helper_add_one_connector
drm_fb_helper_alloc_fbi
drm_fb_helper_blank
drm_fb_helper_cfb_copyarea
drm_fb_helper_cfb_fillrect
drm_fb_helper_cfb_imageblit
drm_fb_helper_check_var
drm_fb_helper_debug_enter
drm_fb_helper_debug_leave
drm_fb_helper_fill_fix
drm_fb_helper_fill_var
drm_fb_helper_fini
drm_fb_helper_hotplug_event
drm_fb_helper_init
drm_fb_helper_initial_config
drm_fb_helper_ioctl
drm_fb_helper_lastclose
drm_fb_helper_output_poll_changed
drm_fb_helper_pan_display
drm_fb_helper_prepare
drm_fb_helper_remove_one_connector
drm_fb_helper_setcmap
drm_fb_helper_set_par
drm_fb_helper_set_suspend
drm_fb_helper_set_suspend_unlocked
drm_fb_helper_single_add_all_connectors
drm_fb_helper_unregister_fbi
drm_format_plane_cpp
drm_framebuffer_cleanup
drm_framebuffer_init
drm_framebuffer_unregister_private
drm_gem_dmabuf_kmap
drm_gem_dmabuf_kunmap
drm_gem_dmabuf_mmap
drm_gem_dmabuf_release
drm_gem_dmabuf_vmap
drm_gem_dmabuf_vunmap
drm_gem_fb_create_handle
drm_gem_fb_destroy
drm_gem_handle_create
drm_gem_handle_delete
drm_gem_map_attach
drm_gem_map_detach
drm_gem_map_dma_buf
drm_gem_object_free
drm_gem_object_init
drm_gem_object_lookup
drm_gem_object_put_unlocked
drm_gem_object_release
drm_gem_prime_export
drm_gem_prime_fd_to_handle
drm_gem_prime_handle_to_fd
drm_gem_prime_import
drm_gem_private_object_init
drm_gem_unmap_dma_buf
drm_get_edid
drm_get_edid_switcheroo
drm_get_format_name
drm_get_max_iomem
drm_global_item_ref
drm_global_item_unref
drm_handle_vblank
drm_hdmi_avi_infoframe_from_display_mode
drm_hdmi_vendor_infoframe_from_display_mode
drm_helper_connector_dpms
drm_helper_disable_unused_functions
drm_helper_hpd_irq_event
drm_helper_mode_fill_fb_struct
drm_helper_probe_single_connector_modes
drm_helper_resume_force_mode
drm_i2c_encoder_detect
drm_i2c_encoder_init
drm_i2c_encoder_mode_fixup
drm_i2c_encoder_restore
drm_i2c_encoder_save
drm_invalid_op
drm_ioctl
drm_irq_install
drm_irq_uninstall
drm_is_current_master
drm_kms_helper_hotplug_event
drm_kms_helper_is_poll_worker
drm_kms_helper_poll_disable
drm_kms_helper_poll_enable
drm_kms_helper_poll_fini
drm_kms_helper_poll_init
drm_match_cea_mode
drm_mm_init
drm_mm_insert_node_in_range
drm_mm_print
drm_mm_remove_node
drm_mm_takedown
drm_mode_config_cleanup
drm_mode_config_init
drm_mode_config_reset
drm_mode_copy
drm_mode_create_dvi_i_properties
drm_mode_create_scaling_mode_property
drm_mode_create_tv_properties
drm_mode_crtc_set_gamma_size
drm_mode_debug_printmodeline
drm_mode_destroy
drm_mode_duplicate
drm_mode_equal
drm_mode_get_hv_timing
drm_mode_is_420_only
drm_mode_legacy_fb_format
drm_mode_object_find
drm_mode_object_put
drm_mode_probed_add
drm_mode_set_crtcinfo
drm_modeset_lock
drm_modeset_lock_all
drm_modeset_lock_all_ctx
drm_mode_set_name
drm_modeset_unlock
drm_modeset_unlock_all
drm_mode_vrefresh
drm_object_attach_property
drm_object_property_set_value
drm_open
drm_plane_cleanup
drm_plane_create_alpha_property
drm_plane_create_color_properties
drm_plane_create_zpos_immutable_property
drm_plane_create_zpos_property
drm_plane_force_disable
drm_plane_init
drm_poll
drm_primary_helper_destroy
drm_primary_helper_funcs
drm_prime_gem_destroy
drm_prime_pages_to_sg
drm_prime_sg_to_page_addr_arrays
drm_printf
__drm_printfn_seq_file
drm_property_add_enum
drm_property_create
drm_property_create_enum
drm_property_create_range
__drm_puts_seq_file
drm_read
drm_release
drm_scdc_read
drm_scdc_write
drm_sched_dependency_optimized
drm_sched_entity_destroy
drm_sched_entity_fini
drm_sched_entity_flush
drm_sched_entity_init
drm_sched_entity_push_job
drm_sched_entity_set_rq
drm_sched_fini
drm_sched_hw_job_reset
drm_sched_init
drm_sched_job_init
drm_sched_job_recovery
drm_send_event_locked
drm_syncobj_create
drm_syncobj_find
drm_syncobj_find_fence
drm_syncobj_free
drm_syncobj_get_fd
drm_syncobj_get_handle
drm_syncobj_replace_fence
drm_universal_plane_init
drm_vblank_init
drm_vma_node_allow
drm_vma_node_is_allowed
drm_vma_node_revoke
dst_release
dump_stack
__dynamic_dev_dbg
__dynamic_netdev_dbg
__dynamic_pr_debug
efi
elfcorehdr_addr
emergency_restart
empty_zero_page
enable_irq
errno_to_blk_status
ether_setup
eth_get_headlen
eth_platform_get_mac_address
ethtool_convert_legacy_u32_to_link_mode
ethtool_convert_link_mode_to_legacy_u32
__ethtool_get_link_ksettings
ethtool_intersect_link_masks
ethtool_op_get_link
ethtool_op_get_ts_info
eth_type_trans
eth_validate_addr
event_triggers_call
ex_handler_default
ex_handler_refcount
fasync_helper
fc_attach_transport
fc_block_scsi_eh
fc_disc_config
fc_disc_init
fc_eh_host_reset
fc_eh_timed_out
fc_elsct_init
fc_elsct_send
fc_exch_init
fc_exch_mgr_alloc
fc_exch_mgr_free
fc_exch_mgr_list_clone
fc_exch_recv
fc_fabric_login
fc_fabric_logoff
_fc_frame_alloc
fc_frame_alloc_fill
fc_get_event_number
fc_get_host_port_state
fc_get_host_speed
fc_get_host_stats
fc_host_post_event
fc_host_post_vendor_event
fc_lport_bsg_request
fc_lport_config
fc_lport_destroy
fc_lport_flogi_resp
fc_lport_init
fc_lport_logo_resp
fc_lport_reset
fcoe_check_wait_queue
fcoe_clean_pending_queue
fcoe_ctlr_destroy
fcoe_ctlr_device_add
fcoe_ctlr_device_delete
fcoe_ctlr_els_send
fcoe_ctlr_get_lesb
fcoe_ctlr_init
fcoe_ctlr_link_down
fcoe_ctlr_link_up
fcoe_ctlr_recv
fcoe_ctlr_recv_flogi
fcoe_fc_crc
fcoe_fcf_get_selected
fcoe_get_lesb
fcoe_get_paged_crc_eof
fcoe_get_wwn
fcoe_link_speed_update
fcoe_queue_timer
fcoe_start_io
fcoe_transport_attach
fcoe_transport_detach
fcoe_validate_vport_create
fcoe_wwn_from_mac
fcoe_wwn_to_str
fc_release_transport
fc_remote_port_add
fc_remote_port_delete
fc_remote_port_rolechg
fc_remove_host
fc_rport_terminate_io
fc_set_mfs
fc_set_rport_loss_tmo
fc_slave_alloc
fc_vport_create
fc_vport_id_lookup
fc_vport_setlink
fc_vport_terminate
__fdget
fd_install
__fentry__
fget
__fib_lookup
fib_table_lookup
filemap_fault
filp_close
filp_open
find_first_bit
find_first_zero_bit
find_get_pid
find_last_bit
find_next_bit
find_next_zero_bit
find_pid_ns
find_vma
finish_wait
firmware_request_nowarn
fixed_size_llseek
flow_keys_dissector
flush_delayed_work
flush_signals
flush_work
flush_workqueue
follow_pfn
force_sig
fortify_panic
fput
free_cpumask_var
free_fib_info
free_irq
free_irq_cpu_rmap
free_netdev
__free_pages
free_pages
free_percpu
from_kgid
from_kuid
fs_bio_set
gcd
generate_random_uuid
generic_end_io_acct
generic_handle_irq
generic_make_request
generic_start_io_acct
genlmsg_put
genl_register_family
genl_unregister_family
get_device
__get_free_pages
get_gendisk
get_pid_task
get_random_bytes
__get_task_comm
get_task_mm
get_task_pid
get_unused_fd_flags
__get_user_2
__get_user_4
__get_user_8
get_user_pages
get_user_pages_remote
get_zeroed_page
groups_alloc
groups_free
handle_simple_irq
hdmi_avi_infoframe_pack
hdmi_infoframe_pack
hrtimer_cancel
hrtimer_forward
hrtimer_init
hrtimer_start_range_ns
hrtimer_try_to_cancel
__hw_addr_sync_dev
__hw_addr_unsync_dev
hwmon_device_register
hwmon_device_register_with_groups
hwmon_device_register_with_info
hwmon_device_unregister
i2c_add_adapter
i2c_bit_add_bus
i2c_bit_algo
i2c_del_adapter
i2c_new_device
i2c_smbus_read_byte_data
i2c_smbus_write_byte_data
i2c_transfer
i2c_unregister_device
__ib_alloc_cq
ib_alloc_device
ib_alloc_odp_umem
__ib_alloc_pd
ib_attach_mcast
ib_cache_gid_parse_type_str
ib_cache_gid_type_str
ib_cancel_mad
ib_cm_init_qp_attr
ib_cm_insert_listen
ib_cm_listen
ib_cm_notify
ibcm_reject_msg
ib_copy_path_rec_from_user
ib_copy_path_rec_to_user
ib_copy_qp_attr_to_user
ib_create_ah_from_wc
ib_create_cm_id
__ib_create_cq
ib_create_qp
ib_create_qp_security
ib_create_send_mad
ib_dealloc_device
ib_dealloc_pd
ib_dealloc_xrcd
ib_destroy_cm_id
ib_destroy_cq
ib_destroy_qp
ib_destroy_rwq_ind_table
ib_destroy_wq
ib_detach_mcast
ib_dispatch_event
ib_find_cached_pkey
ib_free_cq
ib_free_recv_mad
ib_free_send_mad
ib_get_cached_pkey
ib_get_cached_port_state
ib_get_eth_speed
ib_get_gids_from_rdma_hdr
ib_get_mad_data_offset
ib_get_net_dev_by_params
ib_get_rdma_header_version
ib_get_rmpp_segment
ib_init_ah_attr_from_path
ib_init_ah_attr_from_wc
ib_init_ah_from_mcmember
ib_is_mad_class_rmpp
ib_mad_kernel_rmpp_agent
ib_modify_mad
ib_modify_port
ib_modify_qp
ib_modify_qp_is_ok
ib_modify_qp_with_udata
ibnl_put_attr
ibnl_put_msg
ib_open_qp
ib_post_send_mad
ib_process_cq_direct
ib_query_pkey
ib_query_port
ib_query_qp
ib_query_srq
ib_rdmacg_try_charge
ib_rdmacg_uncharge
ib_register_client
ib_register_device
ib_register_event_handler
ib_register_mad_agent
ib_response_mad
ib_sa_cancel_query
ib_sa_free_multicast
ib_sa_get_mcmember_rec
ib_sa_guid_info_rec_query
ib_sa_join_multicast
ib_sa_path_rec_get
ib_sa_register_client
ib_sa_sendonly_fullmem_support
ib_sa_unregister_client
ib_send_cm_apr
ib_send_cm_drep
ib_send_cm_dreq
ib_send_cm_lap
ib_send_cm_mra
ib_send_cm_rej
ib_send_cm_rep
ib_send_cm_req
ib_send_cm_rtu
ib_send_cm_sidr_rep
ib_send_cm_sidr_req
ib_set_client_data
ib_sg_to_pages
ib_ud_header_init
ib_ud_header_pack
ib_ud_ip4_csum
ib_umem_copy_from
ib_umem_get
ib_umem_odp_map_dma_pages
ib_umem_odp_unmap_dma_pages
ib_umem_page_count
ib_umem_release
ib_unregister_client
ib_unregister_device
ib_unregister_event_handler
ib_unregister_mad_agent
ib_uverbs_get_ucontext
ib_wc_status_msg
ida_alloc_range
ida_destroy
ida_free
idr_alloc
idr_alloc_cyclic
idr_alloc_u32
idr_destroy
idr_find
idr_for_each
idr_get_next
idr_get_next_ul
idr_preload
idr_remove
idr_replace
igrab
in6_dev_finish_destroy
in_dev_finish_destroy
in_egroup_p
__inet6_lookup_established
inet_get_local_port_range
__inet_lookup_established
in_group_p
init_net
__init_rwsem
init_srcu_struct
init_task
init_timer_key
init_uts_ns
init_wait_entry
__init_waitqueue_head
interval_tree_insert
interval_tree_iter_first
interval_tree_iter_next
interval_tree_remove
int_to_scsilun
invalidate_partition
iomem_resource
iommu_get_domain_for_dev
iommu_iova_to_phys
iommu_map
iommu_unmap
ioread16
ioread16be
ioread32
ioread32be
ioread8
ioremap_cache
ioremap_nocache
ioremap_wc
io_schedule
io_schedule_timeout
iounmap
iowrite16
iowrite32
iowrite32be
__iowrite32_copy
__iowrite64_copy
iowrite8
ip6_dst_hoplimit
ip_compute_csum
ip_mc_dec_group
ip_mc_inc_group
ipmi_create_user
ipmi_destroy_user
ipmi_free_recv_msg
ipmi_poll_interface
ipmi_request_settime
ipmi_set_gets_events
ipmi_set_my_address
ipmi_smi_msg_received
ipmi_unregister_smi
ipmi_validate_addr
ip_route_output_flow
ip_send_check
ip_tos2prio
iput
__ipv6_addr_type
ipv6_ext_hdr
ipv6_find_hdr
ipv6_skip_exthdr
ipv6_stub
irq_cpu_rmap_add
irq_create_mapping
__irq_domain_add
irq_domain_remove
irq_find_mapping
irq_modify_status
irq_poll_complete
irq_poll_disable
irq_poll_enable
irq_poll_init
irq_poll_sched
irq_set_affinity_hint
irq_set_affinity_notifier
irq_set_chip_and_handler_name
irq_to_desc
is_acpi_device_node
iscsi_boot_create_ethernet
iscsi_boot_create_host_kset
iscsi_boot_create_initiator
iscsi_boot_create_target
iscsi_boot_destroy_kset
__iscsi_complete_pdu
iscsi_complete_scsi_task
iscsi_conn_bind
iscsi_conn_failure
iscsi_conn_get_param
iscsi_conn_send_pdu
iscsi_conn_setup
iscsi_conn_start
iscsi_conn_stop
iscsi_conn_teardown
iscsi_create_endpoint
iscsi_create_iface
iscsi_destroy_endpoint
iscsi_destroy_iface
iscsi_eh_abort
iscsi_eh_device_reset
iscsi_eh_recover_target
iscsi_eh_session_reset
iscsi_get_port_speed_name
iscsi_get_port_state_name
__iscsi_get_task
iscsi_host_add
iscsi_host_alloc
iscsi_host_for_each_session
iscsi_host_free
iscsi_host_get_param
iscsi_host_remove
iscsi_itt_to_task
iscsi_lookup_endpoint
iscsi_offload_mesg
__iscsi_put_task
iscsi_put_task
iscsi_queuecommand
iscsi_register_transport
iscsi_session_failure
iscsi_session_get_param
iscsi_session_recovery_timedout
iscsi_session_setup
iscsi_session_teardown
iscsi_set_param
iscsi_suspend_queue
iscsi_target_alloc
iscsi_unregister_transport
is_uv_system
iw_cm_accept
iw_cm_connect
iw_cm_disconnect
iw_cm_init_qp_attr
iw_cm_listen
iw_cm_reject
iwcm_reject_msg
iw_create_cm_id
iw_destroy_cm_id
jiffies
jiffies_64
jiffies_to_msecs
jiffies_to_timespec64
jiffies_to_usecs
kallsyms_lookup_name
kasprintf
kernel_fpu_begin
kernel_fpu_end
kernel_recvmsg
kernel_sendmsg
kernel_setsockopt
kfree
kfree_call_rcu
kfree_const
kfree_skb
kgdb_active
kgdb_breakpoint
kill_fasync
__kmalloc
kmalloc_caches
__kmalloc_node
kmalloc_order_trace
kmem_cache_alloc
kmem_cache_alloc_node
kmem_cache_alloc_node_trace
kmem_cache_alloc_trace
kmem_cache_create
kmem_cache_create_usercopy
kmem_cache_destroy
kmem_cache_free
kmem_cache_shrink
kmemdup
kobject_add
kobject_create_and_add
kobject_del
kobject_get
kobject_init
kobject_init_and_add
kobject_put
kobject_set_name
kobject_uevent
kobject_uevent_env
krealloc
kset_create_and_add
kset_find_obj
kset_register
kset_unregister
ksize
kstrdup
kstrdup_const
kstrndup
kstrtobool
kstrtobool_from_user
kstrtoint
kstrtoint_from_user
kstrtoll
kstrtoll_from_user
kstrtou16
kstrtou8
kstrtouint
kstrtouint_from_user
kstrtoul_from_user
kstrtoull
kstrtoull_from_user
kthread_bind
kthread_create_on_node
kthread_park
kthread_should_stop
kthread_stop
kthread_unpark
ktime_get
ktime_get_coarse_real_ts64
ktime_get_raw
ktime_get_raw_ts64
ktime_get_real_seconds
ktime_get_real_ts64
ktime_get_seconds
ktime_get_ts64
ktime_get_with_offset
kvasprintf
kvfree
kvmalloc_node
kzfree
led_classdev_resume
led_classdev_suspend
led_classdev_unregister
libfc_vport_create
__list_add_valid
__list_del_entry_valid
llist_add_batch
__local_bh_enable_ip
__lock_page
lock_page_memcg
lockref_get
lock_sock_nested
make_kgid
make_kuid
mark_page_accessed
match_strdup
match_string
match_token
mdio45_probe
mdiobus_alloc_size
mdiobus_free
mdiobus_get_phy
__mdiobus_register
mdiobus_unregister
mdio_mii_ioctl
memchr
memchr_inv
memcmp
memcpy
memdup_user
memdup_user_nul
memmove
memory_read_from_buffer
memparse
mempool_alloc
mempool_alloc_slab
mempool_create
mempool_create_node
mempool_destroy
mempool_free
mempool_free_slab
mempool_kfree
mempool_kmalloc
memscan
mem_section
memset
memzero_explicit
metadata_dst_alloc
mfd_add_devices
mfd_remove_devices
misc_deregister
misc_register
mlxfw_firmware_flash
__mmdrop
mmput
__mmu_notifier_register
mmu_notifier_register
mmu_notifier_unregister
mmu_notifier_unregister_no_release
mod_delayed_work_on
mod_timer
mod_timer_pending
__module_get
module_layout
module_put
module_refcount
__msecs_to_jiffies
msleep
msleep_interruptible
__mutex_init
mutex_lock
mutex_lock_interruptible
mutex_lock_killable
mutex_trylock
mutex_unlock
mxm_wmi_call_mxds
mxm_wmi_call_mxmx
mxm_wmi_supported
__napi_alloc_skb
napi_complete_done
napi_consume_skb
napi_disable
napi_get_frags
napi_gro_flush
napi_gro_frags
napi_gro_receive
napi_hash_del
__napi_schedule
__napi_schedule_irqoff
napi_schedule_prep
__ndelay
ndo_dflt_bridge_getlink
ndo_dflt_fdb_add
nd_tbl
neigh_destroy
__neigh_event_send
neigh_lookup
netdev_alloc_frag
__netdev_alloc_skb
netdev_bind_sb_channel_queue
netdev_crit
netdev_err
netdev_features_change
netdev_info
netdev_lower_get_next
netdev_master_upper_dev_get
netdev_master_upper_dev_get_rcu
netdev_notice
netdev_printk
netdev_reset_tc
netdev_rss_key_fill
netdev_rx_handler_register
netdev_rx_handler_unregister
netdev_set_num_tc
netdev_set_sb_channel
netdev_set_tc_queue
netdev_unbind_sb_channel
netdev_update_features
netdev_walk_all_upper_dev_rcu
netdev_warn
netif_carrier_off
netif_carrier_on
netif_device_attach
netif_device_detach
netif_get_num_default_rss_queues
netif_napi_add
netif_napi_del
netif_receive_skb
netif_rx
netif_schedule_queue
netif_set_real_num_rx_queues
netif_set_real_num_tx_queues
netif_set_xps_queue
netif_tx_stop_all_queues
netif_tx_wake_queue
netlink_broadcast
netlink_unicast
net_ratelimit
nla_find
nla_parse
nla_put
nla_validate
node_data
__node_distance
node_states
node_to_cpumask_map
no_llseek
nonseekable_open
noop_llseek
nr_cpu_ids
nr_node_ids
nsecs_to_jiffies
ns_to_timespec
ns_to_timespec64
ns_to_timeval
numa_node
nvme_alloc_request
nvme_cancel_request
nvme_change_ctrl_state
nvme_cleanup_cmd
nvme_complete_async_event
nvme_complete_rq
nvme_disable_ctrl
nvme_enable_ctrl
nvme_fc_register_localport
nvme_fc_register_remoteport
nvme_fc_set_remoteport_devloss
nvme_fc_unregister_localport
nvme_fc_unregister_remoteport
nvme_init_ctrl
nvme_init_identify
nvme_io_timeout
nvme_kill_queues
nvme_remove_namespaces
nvme_reset_ctrl
nvme_reset_ctrl_sync
nvme_set_queue_count
nvme_setup_cmd
nvme_shutdown_ctrl
nvme_start_ctrl
nvme_start_freeze
nvme_start_queues
nvme_stop_ctrl
nvme_stop_queues
nvme_submit_sync_cmd
nvmet_fc_rcv_fcp_abort
nvmet_fc_rcv_fcp_req
nvmet_fc_rcv_ls_req
nvmet_fc_register_targetport
nvmet_fc_unregister_targetport
nvme_unfreeze
nvme_uninit_ctrl
nvme_wait_freeze
nvme_wait_freeze_timeout
nvme_wq
of_led_classdev_register
on_each_cpu
orderly_poweroff
out_of_line_wait_on_bit
out_of_line_wait_on_bit_lock
override_creds
__page_file_index
__page_frag_cache_drain
page_frag_free
__page_mapcount
page_mapped
page_offset_base
page_pool_alloc_pages
page_pool_create
page_pool_destroy
__page_pool_put_page
pagevec_lookup_range
pagevec_lookup_range_tag
__pagevec_release
panic
panic_notifier_list
param_array_ops
param_get_int
param_ops_bool
param_ops_byte
param_ops_charp
param_ops_int
param_ops_long
param_ops_short
param_ops_string
param_ops_uint
param_ops_ullong
param_ops_ulong
param_ops_ushort
param_set_bool
param_set_int
pat_enabled
pci_alloc_irq_vectors_affinity
pci_assign_unassigned_bus_resources
pcibios_resource_to_bus
pci_bus_resource_n
pci_bus_type
pci_cfg_access_lock
pci_cfg_access_unlock
pci_choose_state
pci_cleanup_aer_uncorrect_error_status
pci_clear_master
pci_clear_mwi
pci_d3cold_disable
pci_dev_driver
pci_dev_get
pci_device_is_present
pci_dev_present
pci_dev_put
pci_disable_device
pci_disable_link_state
pci_disable_msi
pci_disable_msix
pci_disable_pcie_error_reporting
pci_disable_rom
pci_disable_sriov
pcie_bandwidth_available
pcie_capability_clear_and_set_word
pcie_capability_read_dword
pcie_capability_read_word
pcie_capability_write_word
pcie_flr
pcie_get_speed_cap
pcie_get_width_cap
pci_enable_atomic_ops_to_root
pci_enable_device
pci_enable_device_mem
pci_enable_msi
pci_enable_msix_range
pci_enable_pcie_error_reporting
pci_enable_rom
pci_enable_sriov
pci_enable_wake
pcie_print_link_status
pcie_relaxed_ordering_enabled
pcie_set_readrq
pci_find_capability
pci_find_ext_capability
pci_free_irq
pci_free_irq_vectors
pci_get_class
pci_get_device
pci_get_domain_bus_and_slot
pci_get_slot
pci_ignore_hotplug
pci_intx
pci_iomap
pci_ioremap_bar
pci_iounmap
pci_irq_get_affinity
pci_irq_vector
pci_map_rom
pcim_enable_device
pcim_iomap_regions
pcim_iomap_table
pci_num_vf
pci_platform_rom
pci_prepare_to_sleep
pci_read_config_byte
pci_read_config_dword
pci_read_config_word
pci_read_vpd
__pci_register_driver
pci_release_regions
pci_release_resource
pci_release_selected_regions
pci_request_irq
pci_request_regions
pci_request_selected_regions
pci_rescan_bus
pci_resize_resource
pci_restore_state
pci_save_state
pci_select_bars
pci_set_master
pci_set_mwi
pci_set_power_state
pci_sriov_configure_simple
pci_sriov_get_totalvfs
pci_sriov_set_totalvfs
pci_stop_and_remove_bus_device
pci_stop_and_remove_bus_device_locked
pci_try_set_mwi
pci_unmap_rom
pci_unregister_driver
pci_vfs_assigned
pci_vpd_find_info_keyword
pci_vpd_find_tag
pci_wait_for_pending_transaction
pci_wake_from_d3
pci_walk_bus
pci_write_config_byte
pci_write_config_dword
pci_write_config_word
pcix_set_mmrbc
PDE_DATA
__per_cpu_offset
perf_tp_event
perf_trace_buf_alloc
perf_trace_run_bpf_submit
pgprot_writecombine
phy_attached_info
phy_connect
phy_disconnect
phy_ethtool_ksettings_get
phy_ethtool_ksettings_set
phy_ethtool_sset
phy_mii_ioctl
phys_base
physical_mask
phy_start
phy_start_aneg
phy_stop
pid_task
pid_vnr
platform_bus_type
pm_genpd_add_device
pm_genpd_init
pm_genpd_remove_device
pm_power_off
pm_runtime_allow
__pm_runtime_disable
pm_runtime_enable
pm_runtime_forbid
__pm_runtime_idle
__pm_runtime_resume
pm_runtime_set_autosuspend_delay
__pm_runtime_set_status
__pm_runtime_suspend
__pm_runtime_use_autosuspend
pm_schedule_suspend
pm_vt_switch_required
pm_vt_switch_unregister
power_supply_is_system_supplied
prandom_bytes
prandom_seed
prandom_u32
__preempt_count
prepare_creds
prepare_to_wait
prepare_to_wait_event
prepare_to_wait_exclusive
print_hex_dump
printk
__printk_ratelimit
print_stack_trace
proc_create_data
proc_dointvec
proc_mkdir
proc_mkdir_mode
proc_remove
proc_symlink
__pskb_copy_fclone
pskb_expand_head
__pskb_pull_tail
___pskb_trim
ptp_clock_event
ptp_clock_index
ptp_clock_register
ptp_clock_unregister
ptp_find_pin
__put_cred
put_device
__put_devmap_managed_page
put_disk
__put_net
__put_page
put_pid
__put_task_struct
put_unused_fd
__put_user_1
__put_user_2
__put_user_4
__put_user_8
pv_cpu_ops
pv_irq_ops
pv_lock_ops
pv_mmu_ops
qed_get_eth_ops
qed_put_eth_ops
queue_delayed_work_on
queued_read_lock_slowpath
queued_write_lock_slowpath
queue_work_on
radix_tree_delete
radix_tree_gang_lookup
__radix_tree_insert
radix_tree_iter_delete
radix_tree_lookup
radix_tree_lookup_slot
radix_tree_next_chunk
__radix_tree_next_slot
radix_tree_preload
radix_tree_tagged
raid_class_attach
raid_class_release
___ratelimit
raw_notifier_call_chain
raw_notifier_chain_register
raw_notifier_chain_unregister
_raw_read_lock
_raw_read_lock_bh
_raw_read_lock_irq
_raw_read_lock_irqsave
_raw_read_unlock_bh
_raw_read_unlock_irqrestore
_raw_spin_lock
_raw_spin_lock_bh
_raw_spin_lock_irq
_raw_spin_lock_irqsave
_raw_spin_trylock
_raw_spin_unlock_bh
_raw_spin_unlock_irqrestore
_raw_write_lock
_raw_write_lock_bh
_raw_write_lock_irq
_raw_write_lock_irqsave
_raw_write_unlock_bh
_raw_write_unlock_irqrestore
rb_erase
__rb_erase_color
rb_first
rb_first_postorder
__rb_insert_augmented
rb_insert_color
rb_next
rb_next_postorder
rb_replace_node
rbt_ib_umem_for_each_in_range
rbt_ib_umem_lookup
rcu_barrier
rdma_addr_cancel
rdma_addr_size
rdma_create_ah
rdma_create_user_ah
rdma_destroy_ah
rdma_destroy_ah_attr
rdma_find_gid
rdma_find_gid_by_port
rdma_get_gid_attr
rdma_is_zero_gid
rdma_move_ah_attr
rdma_nl_multicast
rdma_nl_register
rdma_nl_unicast
rdma_nl_unicast_wait
rdma_nl_unregister
rdma_node_get_transport
rdma_port_get_link_layer
rdma_put_gid_attr
rdma_query_ah
rdma_query_gid
rdma_resolve_ip
rdma_restrack_del
rdma_roce_rescan_device
rdma_set_cq_moderation
rdma_translate_ip
read_cache_pages
recalc_sigpending
refcount_dec_and_mutex_lock
refcount_dec_and_test_checked
refcount_inc_checked
refcount_inc_not_zero_checked
register_acpi_notifier
register_blkdev
__register_chrdev
register_chrdev_region
register_fib_notifier
register_inet6addr_notifier
register_inetaddr_notifier
register_netdev
register_netdevice_notifier
register_netevent_notifier
register_net_sysctl
__register_nmi_handler
register_pernet_subsys
register_reboot_notifier
release_firmware
release_pages
__release_region
release_sock
remap_pfn_range
remove_conflicting_framebuffers
remove_proc_entry
remove_wait_queue
request_firmware
request_firmware_direct
request_firmware_nowait
__request_module
__request_region
request_threaded_irq
reservation_object_add_excl_fence
reservation_object_add_shared_fence
reservation_object_get_fences_rcu
reservation_object_reserve_shared
reservation_object_wait_timeout_rcu
reservation_ww_class
reset_devices
revert_creds
rhashtable_destroy
rhashtable_free_and_destroy
rhashtable_init
rhashtable_insert_slow
rhashtable_walk_enter
rhashtable_walk_exit
rhashtable_walk_next
rhashtable_walk_start_check
rhashtable_walk_stop
rhltable_init
rht_bucket_nested
rht_bucket_nested_insert
ring_buffer_event_data
roce_gid_type_mask_support
round_jiffies
round_jiffies_relative
rps_may_expire_flow
rt6_lookup
rtc_time64_to_tm
rtnl_is_locked
rtnl_lock
rtnl_trylock
rtnl_unlock
sas_attach_transport
sas_disable_tlr
sas_enable_tlr
sas_end_device_alloc
sas_expander_alloc
sas_is_tlr_enabled
sas_phy_add
sas_phy_alloc
sas_phy_free
sas_port_add
sas_port_add_phy
sas_port_alloc_num
sas_port_delete
sas_port_delete_phy
sas_port_free
sas_read_port_mode_page
sas_release_transport
sas_remove_host
sas_rphy_add
save_stack_trace
save_stack_trace_tsk
sbitmap_queue_clear
__sbitmap_queue_get
sched_setscheduler
schedule
schedule_hrtimeout
schedule_hrtimeout_range
schedule_timeout
schedule_timeout_interruptible
schedule_timeout_uninterruptible
scmd_printk
scnprintf
screen_info
scsi_add_device
scsi_add_host_with_dma
scsi_block_requests
scsi_build_sense_buffer
scsi_change_queue_depth
scsi_device_get
scsi_device_lookup
scsi_device_put
scsi_device_set_state
scsi_device_type
scsi_dma_map
scsi_dma_unmap
__scsi_execute
scsi_get_vpd_page
scsi_host_alloc
scsi_host_busy
scsi_host_get
scsi_host_lookup
scsi_host_put
scsi_internal_device_block_nowait
scsi_internal_device_unblock_nowait
scsi_is_fc_rport
scsi_is_host_device
scsi_is_sdev_device
__scsi_iterate_devices
scsilun_to_int
scsi_normalize_sense
scsi_print_command
scsi_register_driver
scsi_remove_device
scsi_remove_host
scsi_remove_target
scsi_sanitize_inquiry_string
scsi_scan_host
scsi_track_queue_full
scsi_unblock_requests
sdev_prefix_printk
secpath_dup
security_d_instantiate
send_sig
seq_lseek
seq_open
seq_printf
seq_putc
seq_puts
seq_read
seq_release
seq_write
set_cpus_allowed_ptr
set_current_groups
set_device_ro
set_disk_ro
set_freezable
set_memory_array_uc
set_memory_array_wb
set_memory_uc
set_memory_wb
set_memory_wc
set_normalized_timespec
set_normalized_timespec64
set_page_dirty
set_page_dirty_lock
set_user_nice
sg_alloc_table_from_pages
sg_copy_from_buffer
sg_copy_to_buffer
sg_free_table
sg_init_table
sg_miter_next
sg_miter_start
sg_miter_stop
sg_next
show_class_attr_string
sigprocmask
si_meminfo
simple_open
simple_read_from_buffer
simple_strtol
simple_strtoul
simple_strtoull
simple_write_to_buffer
single_open
single_release
skb_add_rx_frag
skb_checksum
skb_checksum_help
skb_clone
skb_clone_tx_timestamp
skb_copy
skb_copy_bits
skb_copy_expand
skb_dequeue
__skb_flow_dissect
__skb_get_hash
__skb_gso_segment
skb_gso_validate_mac_len
__skb_pad
skb_pull
skb_push
skb_put
skb_queue_purge
skb_queue_tail
skb_realloc_headroom
skb_store_bits
skb_trim
skb_tstamp_tx
skb_vlan_pop
sme_active
sme_me_mask
smp_call_function_many
smp_call_function_single
snprintf
sn_rtc_cycles_per_second
sock_create_kern
sock_edemux
sock_release
softnet_data
sort
sprintf
__srcu_read_lock
__srcu_read_unlock
sscanf
__stack_chk_fail
starget_for_each_device
strcasecmp
strcat
strchr
strcmp
strcpy
strcspn
strim
strlcat
strlcpy
strlen
strncasecmp
strncat
strncmp
strncpy
strncpy_from_user
strnlen
strnstr
strpbrk
strrchr
strscpy
strsep
strspn
strstr
submit_bio
__sw_hweight32
__sw_hweight64
swiotlb_nr_tbl
switchdev_port_same_parent_id
__symbol_get
__symbol_put
sync_file_create
synchronize_irq
synchronize_net
synchronize_sched
synchronize_srcu
sysfs_add_file_to_group
sysfs_create_bin_file
sysfs_create_file_ns
sysfs_create_group
sysfs_format_mac
sysfs_remove_bin_file
sysfs_remove_file_from_group
sysfs_remove_file_ns
sysfs_remove_group
sysfs_streq
system_state
system_unbound_wq
system_wq
sys_tz
task_active_pid_ns
tasklet_init
tasklet_kill
__tasklet_schedule
__task_pid_nr_ns
tcf_block_cb_register
tcf_block_cb_unregister
tcp_gro_complete
tcp_hashinfo
tc_setup_cb_egdev_register
tc_setup_cb_egdev_unregister
this_cpu_off
time64_to_tm
timecounter_cyc2time
timecounter_init
timecounter_read
to_drm_sched_fence
trace_define_field
trace_event_buffer_commit
trace_event_buffer_lock_reserve
trace_event_buffer_reserve
trace_event_ignore_this_pid
trace_event_raw_init
trace_event_reg
trace_handle_return
__tracepoint_dma_fence_emit
__tracepoint_xdp_exception
trace_print_flags_seq
trace_raw_output_prep
trace_seq_printf
trace_seq_putc
try_module_get
try_wait_for_completion
tsc_khz
ttm_bo_add_to_lru
ttm_bo_clean_mm
ttm_bo_del_sub_from_lru
ttm_bo_device_init
ttm_bo_device_release
ttm_bo_dma_acc_size
ttm_bo_eviction_valuable
ttm_bo_evict_mm
ttm_bo_global_init
ttm_bo_global_release
ttm_bo_init
ttm_bo_init_mm
ttm_bo_init_reserved
ttm_bo_kmap
ttm_bo_kunmap
ttm_bo_lock_delayed_workqueue
ttm_bo_manager_func
ttm_bo_mem_put
ttm_bo_mem_space
ttm_bo_mmap
ttm_bo_move_accel_cleanup
ttm_bo_move_memcpy
ttm_bo_move_to_lru_tail
ttm_bo_move_ttm
ttm_bo_pipeline_move
ttm_bo_put
ttm_bo_unlock_delayed_workqueue
ttm_bo_validate
ttm_bo_wait
ttm_dma_page_alloc_debugfs
ttm_dma_populate
ttm_dma_tt_fini
ttm_dma_tt_init
ttm_dma_unpopulate
ttm_eu_backoff_reservation
ttm_eu_fence_buffer_objects
ttm_eu_reserve_buffers
ttm_fbdev_mmap
ttm_mem_global_init
ttm_mem_global_release
ttm_page_alloc_debugfs
ttm_pool_populate
ttm_pool_unpopulate
ttm_populate_and_map_pages
ttm_sg_tt_init
ttm_tt_bind
ttm_tt_set_placement_caching
ttm_unmap_and_unpopulate_pages
__udelay
udp4_hwcsum
uio_event_notify
__uio_register_device
uio_unregister_device
unlock_page
unlock_page_memcg
unmap_mapping_range
unregister_acpi_notifier
unregister_blkdev
__unregister_chrdev
unregister_chrdev_region
unregister_fib_notifier
unregister_inet6addr_notifier
unregister_inetaddr_notifier
unregister_netdev
unregister_netdevice_notifier
unregister_netevent_notifier
unregister_net_sysctl_table
unregister_nmi_handler
unregister_pernet_subsys
unregister_reboot_notifier
unuse_mm
up
up_read
up_write
__usecs_to_jiffies
use_mm
usleep_range
__uv_cpu_info
_uverbs_alloc
uverbs_copy_to
uverbs_destroy_def_handler
uverbs_get_flags32
uverbs_get_flags64
uverbs_idr_class
__uv_hub_info_list
uv_possible_blades
uv_setup_irq
uv_teardown_irq
vfree
vga_client_register
vgacon_text_force
vga_set_legacy_decoding
vga_switcheroo_client_fb_set
vga_switcheroo_client_probe_defer
vga_switcheroo_fini_domain_pm_ops
vga_switcheroo_handler_flags
vga_switcheroo_init_domain_pm_ops
vga_switcheroo_lock_ddc
vga_switcheroo_process_delayed_switch
vga_switcheroo_register_client
vga_switcheroo_register_handler
vga_switcheroo_unlock_ddc
vga_switcheroo_unregister_client
vga_switcheroo_unregister_handler
vga_tryget
__virt_addr_valid
vlan_dev_real_dev
vlan_dev_vlan_id
vlan_dev_vlan_proto
vmalloc
__vmalloc
vmalloc_base
vmalloc_node
vmalloc_to_page
vmap
vmemmap_base
vm_get_page_prot
vm_insert_page
vm_mmap
vm_munmap
vprintk
vscnprintf
vsnprintf
vsprintf
vunmap
vzalloc
vzalloc_node
wait_for_completion
wait_for_completion_interruptible
wait_for_completion_interruptible_timeout
wait_for_completion_io_timeout
wait_for_completion_killable
wait_for_completion_timeout
wait_on_page_bit
__wake_up
wake_up_bit
__wake_up_locked
wake_up_process
__warn_printk
wmi_evaluate_method
wmi_has_guid
work_busy
write_cache_pages
ww_mutex_lock
ww_mutex_lock_interruptible
ww_mutex_unlock
x86_cpu_to_apicid
x86_dma_fallback_dev
__x86_indirect_thunk_r10
__x86_indirect_thunk_r11
__x86_indirect_thunk_r12
__x86_indirect_thunk_r13
__x86_indirect_thunk_r14
__x86_indirect_thunk_r15
__x86_indirect_thunk_r8
__x86_indirect_thunk_r9
__x86_indirect_thunk_rax
__x86_indirect_thunk_rbp
__x86_indirect_thunk_rbx
__x86_indirect_thunk_rcx
__x86_indirect_thunk_rdi
__x86_indirect_thunk_rdx
__x86_indirect_thunk_rsi
xdp_do_flush_map
xdp_do_redirect
xdp_return_frame
xdp_return_frame_rx_napi
xdp_rxq_info_is_reg
xdp_rxq_info_reg
xdp_rxq_info_reg_mem_model
xdp_rxq_info_unreg
xdp_rxq_info_unused
xfrm_replay_seqhi
xz_dec_end
xz_dec_init
xz_dec_run
yield
zalloc_cpumask_var
zap_vma_ptes
zlib_inflate
zlib_inflateEnd
zlib_inflateInit2
zlib_inflate_workspacesize
2
2
yanl1229(a)163.com
1
0

[PATCH openEuler-21.03 1/2] mm: add pin memory method for checkpoint add restore
by hejingxian 02 Mar '21
by hejingxian 02 Mar '21
02 Mar '21
From: Jingxian He <hejingxian(a)huawei.com>
Date: Mon, 1 Mar 2021 17:35:32 +0800
Subject: [PATCH openEuler-21.03 1/2] mm: add pin memory method for checkpoint add restore
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
We can use the checkpoint and restore in userspace(criu) method to
dump and restore tasks when updating the kernel.
Currently, criu needs dump all memory data of tasks to files.
When the memory size is very large(larger than 1G),
the cost time of the dumping data will be very long(more than 1 min).
By pin the memory data of tasks and collect the corresponding
physical pages mapping info in checkpoint process,
we can remap the physical pages to restore tasks after
upgrading the kernel. This pin memory method can
restore the task data within one second.
The pin memory area info is saved in the reserved memblock,
which can keep usable in the kernel update process.
The pin memory driver provides the following ioctl command for criu:
1) SET_PIN_MEM_AREA:
Set pin memory area, which can be remap to the restore task.
2) CLEAR_PIN_MEM_AREA:
Clear the pin memory area info,
which enable user reset the pin data.
3) REMAP_PIN_MEM_AREA:
Remap the pages of the pin memory to the restore task.
Signed-off-by: Jingxian He <hejingxian(a)huawei.com>
Reviewed-by: Wenliang He <hewenliang4(a)huawei.com>
Reviewed-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
---
arch/arm64/configs/openeuler_defconfig | 2 +
arch/arm64/kernel/setup.c | 9 +
arch/arm64/mm/init.c | 60 +++
drivers/char/Kconfig | 6 +
drivers/char/Makefile | 1 +
drivers/char/pin_memory.c | 208 ++++++++
include/linux/crash_core.h | 5 +
include/linux/pin_mem.h | 78 +++
kernel/crash_core.c | 11 +
mm/Kconfig | 8 +
mm/Makefile | 1 +
mm/huge_memory.c | 61 +++
mm/memory.c | 59 ++
mm/pin_mem.c | 950 +++++++++++++++++++++++++++++++++
14 files changed, 1459 insertions(+)
create mode 100644 drivers/char/pin_memory.c
create mode 100644 include/linux/pin_mem.h
create mode 100644 mm/pin_mem.c
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig
index c5271e7..76fda68 100644
--- a/arch/arm64/configs/openeuler_defconfig
+++ b/arch/arm64/configs/openeuler_defconfig
@@ -1036,6 +1036,7 @@ CONFIG_FRAME_VECTOR=y
# CONFIG_GUP_BENCHMARK is not set
# CONFIG_READ_ONLY_THP_FOR_FS is not set
CONFIG_ARCH_HAS_PTE_SPECIAL=y
+CONFIG_PIN_MEMORY=y
# end of Memory Management options
CONFIG_NET=y
@@ -3282,6 +3283,7 @@ CONFIG_TCG_TIS_ST33ZP24_SPI=y
# CONFIG_RANDOM_TRUST_CPU is not set
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
+CONFIG_PIN_MEMORY_DEV=m
#
# I2C support
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index c1f1fb9..5e282d3 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -50,6 +50,9 @@
#include <asm/efi.h>
#include <asm/xen/hypervisor.h>
#include <asm/mmu_context.h>
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/pin_mem.h>
+#endif
static int num_standard_resources;
static struct resource *standard_resources;
@@ -260,6 +263,12 @@ static void __init request_standard_resources(void)
quick_kexec_res.end <= res->end)
request_resource(res, &quick_kexec_res);
#endif
+#ifdef CONFIG_PIN_MEMORY
+ if (pin_memory_resource.end &&
+ pin_memory_resource.start >= res->start &&
+ pin_memory_resource.end <= res->end)
+ request_resource(res, &pin_memory_resource);
+#endif
}
}
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f3e5a66..8ab5aac 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -42,6 +42,9 @@
#include <linux/sizes.h>
#include <asm/tlb.h>
#include <asm/alternative.h>
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/pin_mem.h>
+#endif
#define ARM64_ZONE_DMA_BITS 30
@@ -78,6 +81,55 @@ static void __init reserve_crashkernel(void)
*/
#define MAX_USABLE_RANGES 2
+#ifdef CONFIG_PIN_MEMORY
+struct resource pin_memory_resource = {
+ .name = "Pin memory",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_RESERVED
+};
+
+static void __init reserve_pin_memory_res(void)
+{
+ unsigned long long mem_start, mem_len;
+ int ret;
+
+ ret = parse_pin_memory(boot_command_line, memblock_phys_mem_size(),
+ &mem_len, &mem_start);
+ if (ret || !mem_len)
+ return;
+
+ mem_len = PAGE_ALIGN(mem_len);
+
+ if (!memblock_is_region_memory(mem_start, mem_len)) {
+ pr_warn("cannot reserve for pin memory: region is not memory!\n");
+ return;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_len)) {
+ pr_warn("cannot reserve for pin memory: region overlaps reserved memory!\n");
+ return;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve for pin memory: base address is not 2MB aligned\n");
+ return;
+ }
+
+ memblock_reserve(mem_start, mem_len);
+ pr_debug("pin memory resource reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ mem_start, mem_start + mem_len, mem_len >> 20);
+
+ pin_memory_resource.start = mem_start;
+ pin_memory_resource.end = mem_start + mem_len - 1;
+}
+#else
+static void __init reserve_pin_memory_res(void)
+{
+}
+#endif /* CONFIG_PIN_MEMORY */
+
#ifdef CONFIG_CRASH_DUMP
static int __init early_init_dt_scan_elfcorehdr(unsigned long node,
const char *uname, int depth, void *data)
@@ -455,6 +507,8 @@ void __init arm64_memblock_init(void)
reserve_park_mem();
#endif
+ reserve_pin_memory_res();
+
reserve_elfcorehdr();
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
@@ -583,6 +637,12 @@ void __init mem_init(void)
/* this will put all unused low memory onto the freelists */
memblock_free_all();
+#ifdef CONFIG_PIN_MEMORY
+ /* pre alloc the pages for pin memory */
+ init_reserve_page_map((unsigned long)pin_memory_resource.start,
+ (unsigned long)(pin_memory_resource.end - pin_memory_resource.start + 1));
+#endif
+
mem_init_print_info(NULL);
/*
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index d229a2d..fbb94b8 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -496,3 +496,9 @@ config RANDOM_TRUST_BOOTLOADER
booloader is trustworthy so it will be added to the kernel's entropy
pool. Otherwise, say N here so it will be regarded as device input that
only mixes the entropy pool.
+
+config PIN_MEMORY_DEV
+ bool "/dev/pinmem character device"
+ default m
+ help
+ pin memory driver
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index ffce287..71d76fd 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
obj-$(CONFIG_XILLYBUS) += xillybus/
obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
obj-$(CONFIG_ADI) += adi.o
+obj-$(CONFIG_PIN_MEMORY_DEV) += pin_memory.o
diff --git a/drivers/char/pin_memory.c b/drivers/char/pin_memory.c
new file mode 100644
index 0000000..f46e056
--- /dev/null
+++ b/drivers/char/pin_memory.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved.
+ * Pin memory driver for checkpoint and restore.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/mm_types.h>
+#include <linux/processor.h>
+#include <uapi/asm-generic/ioctl.h>
+#include <uapi/asm-generic/mman-common.h>
+#include <uapi/asm/setup.h>
+#include <linux/pin_mem.h>
+#include <linux/sched/mm.h>
+
+#define MAX_PIN_MEM_AREA_NUM 16
+struct _pin_mem_area {
+ unsigned long virt_start;
+ unsigned long virt_end;
+};
+
+struct pin_mem_area_set {
+ unsigned int pid;
+ unsigned int area_num;
+ struct _pin_mem_area mem_area[MAX_PIN_MEM_AREA_NUM];
+};
+
+#define PIN_MEM_MAGIC 0x59
+#define _SET_PIN_MEM_AREA 1
+#define _CLEAR_PIN_MEM_AREA 2
+#define _REMAP_PIN_MEM_AREA 3
+#define _FINISH_PIN_MEM_DUMP 4
+#define _PIN_MEM_IOC_MAX_NR 4
+#define SET_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _SET_PIN_MEM_AREA, struct pin_mem_area_set)
+#define CLEAR_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _CLEAR_PIN_MEM_AREA, int)
+#define REMAP_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _REMAP_PIN_MEM_AREA, int)
+#define FINISH_PIN_MEM_DUMP _IOW(PIN_MEM_MAGIC, _FINISH_PIN_MEM_DUMP, int)
+static int set_pin_mem(struct pin_mem_area_set *pmas)
+{
+ int i;
+ int ret = 0;
+ struct _pin_mem_area *pma;
+ struct mm_struct *mm;
+ struct task_struct *task;
+ struct pid *pid_s;
+
+ pid_s = find_get_pid(pmas->pid);
+ if (!pid_s) {
+ pr_warn("Get pid struct fail:%d.\n", pmas->pid);
+ return -EFAULT;
+ }
+ rcu_read_lock();
+ task = pid_task(pid_s, PIDTYPE_PID);
+ if (!task) {
+ pr_warn("Get task struct fail:%d.\n", pmas->pid);
+ goto fail;
+ }
+ mm = get_task_mm(task);
+ for (i = 0; i < pmas->area_num; i++) {
+ pma = &(pmas->mem_area[i]);
+ ret = pin_mem_area(task, mm, pma->virt_start, pma->virt_end);
+ if (ret) {
+ mmput(mm);
+ goto fail;
+ }
+ }
+ mmput(mm);
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return ret;
+
+fail:
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return -EFAULT;
+}
+
+static int set_pin_mem_area(unsigned long arg)
+{
+ struct pin_mem_area_set pmas;
+ void __user *buf = (void __user *)arg;
+
+ if (!access_ok(buf, sizeof(pmas)))
+ return -EFAULT;
+ if (copy_from_user(&pmas, buf, sizeof(pmas)))
+ return -EINVAL;
+ if (pmas.area_num > MAX_PIN_MEM_AREA_NUM) {
+ pr_warn("Input area_num is too large.\n");
+ return -EINVAL;
+ }
+
+ return set_pin_mem(&pmas);
+}
+
+static int pin_mem_remap(unsigned long arg)
+{
+ int pid;
+ struct task_struct *task;
+ struct mm_struct *mm;
+ vm_fault_t ret;
+ void __user *buf = (void __user *)arg;
+ struct pid *pid_s;
+
+ if (!access_ok(buf, sizeof(int)))
+ return -EINVAL;
+ if (copy_from_user(&pid, buf, sizeof(int)))
+ return -EINVAL;
+
+ pid_s = find_get_pid(pid);
+ if (!pid_s) {
+ pr_warn("Get pid struct fail:%d.\n", pid);
+ return -EINVAL;
+ }
+ rcu_read_lock();
+ task = pid_task(pid_s, PIDTYPE_PID);
+ if (!task) {
+ pr_warn("Get task struct fail:%d.\n", pid);
+ goto fault;
+ }
+ mm = get_task_mm(task);
+ ret = do_mem_remap(pid, mm);
+ if (ret) {
+ pr_warn("Handle pin memory remap fail.\n");
+ mmput(mm);
+ goto fault;
+ }
+ mmput(mm);
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return 0;
+
+fault:
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return -EFAULT;
+}
+
+static long pin_memory_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long ret = 0;
+
+ if (_IOC_TYPE(cmd) != PIN_MEM_MAGIC)
+ return -EINVAL;
+ if (_IOC_NR(cmd) > _PIN_MEM_IOC_MAX_NR)
+ return -EINVAL;
+
+ switch (cmd) {
+ case SET_PIN_MEM_AREA:
+ ret = set_pin_mem_area(arg);
+ break;
+ case CLEAR_PIN_MEM_AREA:
+ clear_pin_memory_record();
+ break;
+ case REMAP_PIN_MEM_AREA:
+ ret = pin_mem_remap(arg);
+ break;
+ case FINISH_PIN_MEM_DUMP:
+ ret = finish_pin_mem_dump();
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static const struct file_operations pin_memory_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = pin_memory_ioctl,
+ .compat_ioctl = pin_memory_ioctl,
+};
+
+static struct miscdevice pin_memory_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "pinmem",
+ .fops = &pin_memory_fops,
+};
+
+static int pin_memory_init(void)
+{
+ int err = misc_register(&pin_memory_miscdev);
+
+ if (!err)
+ pr_info("pin_memory init\n");
+ else
+ pr_warn("pin_memory init failed!\n");
+ return err;
+}
+
+static void pin_memory_exit(void)
+{
+ misc_deregister(&pin_memory_miscdev);
+ pr_info("pin_memory ko exists!\n");
+}
+
+module_init(pin_memory_init);
+module_exit(pin_memory_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Euler");
+MODULE_DESCRIPTION("pin memory");
diff --git a/include/linux/crash_core.h b/include/linux/crash_core.h
index fc0ef33..30f0df3 100644
--- a/include/linux/crash_core.h
+++ b/include/linux/crash_core.h
@@ -87,4 +87,9 @@ int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
unsigned long long *crash_size, unsigned long long *crash_base);
+#ifdef CONFIG_PIN_MEMORY
+int __init parse_pin_memory(char *cmdline, unsigned long long system_ram,
+ unsigned long long *pin_size, unsigned long long *pin_base);
+#endif
+
#endif /* LINUX_CRASH_CORE_H */
diff --git a/include/linux/pin_mem.h b/include/linux/pin_mem.h
new file mode 100644
index 0000000..bc8b03e
--- /dev/null
+++ b/include/linux/pin_mem.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved.
+ * Provide the pin memory method for checkpoint and restore task.
+ */
+#ifndef _LINUX_PIN_MEMORY_H
+#define _LINUX_PIN_MEMORY_H
+
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/errno.h>
+#include <linux/mm_types.h>
+#include <linux/err.h>
+#ifdef CONFIG_ARM64
+#include <linux/ioport.h>
+#endif
+
+#define PAGE_BUDDY_MAPCOUNT_VALUE (~PG_buddy)
+
+#define COLLECT_PAGES_FINISH 0
+#define COLLECT_PAGES_NEED_CONTINUE 1
+#define COLLECT_PAGES_FAIL -1
+
+#define COMPOUND_PAD_MASK 0xffffffff
+#define COMPOUND_PAD_START 0x88
+#define COMPOUND_PAD_DELTA 0x40
+#define LIST_POISON4 0xdead000000000400
+#define PAGE_FLAGS_CHECK_RESERVED (1UL << PG_reserved)
+#define SHA256_DIGEST_SIZE 32
+#define next_pme(pme) ((unsigned long *)(pme + 1) + pme->nr_pages)
+#define PIN_MEM_DUMP_MAGIC 0xfeab000000001acd
+struct page_map_entry {
+ unsigned long virt_addr;
+ unsigned int nr_pages;
+ unsigned int is_huge_page;
+ unsigned long redirect_start;
+ unsigned long phy_addr_array[0];
+};
+
+struct page_map_info {
+ int pid;
+ int pid_reserved;
+ unsigned int entry_num;
+ int disable_free_page;
+ struct page_map_entry *pme;
+};
+
+struct pin_mem_dump_info {
+ char sha_digest[SHA256_DIGEST_SIZE];
+ unsigned long magic;
+ unsigned int pin_pid_num;
+ struct page_map_info pmi_array[0];
+};
+
+struct redirect_info {
+ unsigned int redirect_pages;
+ unsigned int redirect_index[0];
+};
+
+extern struct page_map_info *get_page_map_info(int pid);
+extern struct page_map_info *create_page_map_info(int pid);
+extern vm_fault_t do_mem_remap(int pid, struct mm_struct *mm);
+extern vm_fault_t do_anon_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page);
+extern void clear_pin_memory_record(void);
+extern int pin_mem_area(struct task_struct *task, struct mm_struct *mm,
+ unsigned long start_addr, unsigned long end_addr);
+extern vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page);
+extern int finish_pin_mem_dump(void);
+
+/* reserve space for pin memory*/
+#ifdef CONFIG_ARM64
+extern struct resource pin_memory_resource;
+#endif
+extern void init_reserve_page_map(unsigned long map_addr, unsigned long map_size);
+
+#endif /* CONFIG_PIN_MEMORY */
+#endif /* _LINUX_PIN_MEMORY_H */
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index bfed474..2407de3 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -450,6 +450,17 @@ void __init reserve_crashkernel(void)
}
#endif /* CONFIG_ARCH_WANT_RESERVE_CRASH_KERNEL */
+#ifdef CONFIG_PIN_MEMORY
+int __init parse_pin_memory(char *cmdline,
+ unsigned long long system_ram,
+ unsigned long long *pin_size,
+ unsigned long long *pin_base)
+{
+ return __parse_crashkernel(cmdline, system_ram, pin_size, pin_base,
+ "pinmemory=", NULL);
+}
+#endif
+
Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
void *data, size_t data_len)
{
diff --git a/mm/Kconfig b/mm/Kconfig
index 390165f..930dc13 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -859,4 +859,12 @@ config ARCH_HAS_HUGEPD
config MAPPING_DIRTY_HELPERS
bool
+config PIN_MEMORY
+ bool "Support for pin memory"
+ depends on CHECKPOINT_RESTORE
+ help
+ Say y here to enable the pin memory feature for checkpoint
+ and restore. We can pin the memory data of tasks and collect
+ the corresponding physical pages mapping info in checkpoint,
+ and remap the physical pages to restore tasks in restore.
endmenu
diff --git a/mm/Makefile b/mm/Makefile
index d73aed0..4963827 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -120,3 +120,4 @@ obj-$(CONFIG_MEMFD_CREATE) += memfd.o
obj-$(CONFIG_MAPPING_DIRTY_HELPERS) += mapping_dirty_helpers.o
obj-$(CONFIG_PTDUMP_CORE) += ptdump.o
obj-$(CONFIG_PAGE_REPORTING) += page_reporting.o
+obj-$(CONFIG_PIN_MEMORY) += pin_mem.o
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 0bc4a2c..8a11d30 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2996,3 +2996,64 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new)
update_mmu_cache_pmd(vma, address, pvmw->pmd);
}
#endif
+
+#ifdef CONFIG_PIN_MEMORY
+vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page)
+{
+ gfp_t gfp;
+ pgtable_t pgtable;
+ spinlock_t *ptl;
+ pmd_t entry;
+ vm_fault_t ret = 0;
+
+ if (unlikely(anon_vma_prepare(vma)))
+ return VM_FAULT_OOM;
+ if (unlikely(khugepaged_enter(vma, vma->vm_flags)))
+ return VM_FAULT_OOM;
+ gfp = alloc_hugepage_direct_gfpmask(vma);
+ prep_transhuge_page(page);
+ if (mem_cgroup_charge(page, vma->vm_mm, gfp)) {
+ put_page(page);
+ count_vm_event(THP_FAULT_FALLBACK);
+ count_vm_event(THP_FAULT_FALLBACK_CHARGE);
+ return VM_FAULT_FALLBACK;
+ }
+ cgroup_throttle_swaprate(page, gfp);
+
+ pgtable = pte_alloc_one(vma->vm_mm);
+ if (unlikely(!pgtable)) {
+ ret = VM_FAULT_OOM;
+ goto release;
+ }
+ __SetPageUptodate(page);
+ ptl = pmd_lock(vma->vm_mm, pmd);
+ if (unlikely(!pmd_none(*pmd))) {
+ goto unlock_release;
+ } else {
+ ret = check_stable_address_space(vma->vm_mm);
+ if (ret)
+ goto unlock_release;
+ entry = mk_huge_pmd(page, vma->vm_page_prot);
+ entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
+ page_add_new_anon_rmap(page, vma, address, true);
+ lru_cache_add_inactive_or_unevictable(page, vma);
+ pgtable_trans_huge_deposit(vma->vm_mm, pmd, pgtable);
+ set_pmd_at(vma->vm_mm, address, pmd, entry);
+ add_mm_counter(vma->vm_mm, MM_ANONPAGES, HPAGE_PMD_NR);
+ mm_inc_nr_ptes(vma->vm_mm);
+ spin_unlock(ptl);
+ count_vm_event(THP_FAULT_ALLOC);
+ count_memcg_event_mm(vma->vm_mm, THP_FAULT_ALLOC);
+ }
+
+ return 0;
+unlock_release:
+ spin_unlock(ptl);
+release:
+ if (pgtable)
+ pte_free(vma->vm_mm, pgtable);
+ put_page(page);
+ return ret;
+}
+#endif
diff --git a/mm/memory.c b/mm/memory.c
index 50632c4..7b7f1a7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -5248,3 +5248,62 @@ void ptlock_free(struct page *page)
kmem_cache_free(page_ptl_cachep, page->ptl);
}
#endif
+
+#ifdef CONFIG_PIN_MEMORY
+vm_fault_t do_anon_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page)
+{
+ pte_t entry;
+ spinlock_t *ptl;
+ pte_t *pte;
+ vm_fault_t ret = 0;
+
+ if (pte_alloc(vma->vm_mm, pmd))
+ return VM_FAULT_OOM;
+
+ /* See the comment in pte_alloc_one_map() */
+ if (unlikely(pmd_trans_unstable(pmd)))
+ return 0;
+
+ /* Allocate our own private page. */
+ if (unlikely(anon_vma_prepare(vma)))
+ goto oom;
+
+ if (mem_cgroup_charge(page, vma->vm_mm, GFP_KERNEL))
+ goto oom_free_page;
+ cgroup_throttle_swaprate(page, GFP_KERNEL);
+
+ __SetPageUptodate(page);
+
+ entry = mk_pte(page, vma->vm_page_prot);
+ if (vma->vm_flags & VM_WRITE)
+ entry = pte_mkwrite(pte_mkdirty(entry));
+ pte = pte_offset_map_lock(vma->vm_mm, pmd, address,
+ &ptl);
+ if (!pte_none(*pte)) {
+ ret = VM_FAULT_FALLBACK;
+ goto release;
+ }
+
+ ret = check_stable_address_space(vma->vm_mm);
+ if (ret)
+ goto release;
+ inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
+ page_add_new_anon_rmap(page, vma, address, false);
+ lru_cache_add_inactive_or_unevictable(page, vma);
+
+ set_pte_at(vma->vm_mm, address, pte, entry);
+ /* No need to invalidate - it was non-present before */
+ update_mmu_cache(vma, address, pte);
+unlock:
+ pte_unmap_unlock(pte, ptl);
+ return ret;
+release:
+ put_page(page);
+ goto unlock;
+oom_free_page:
+ put_page(page);
+oom:
+ return VM_FAULT_OOM;
+}
+#endif
diff --git a/mm/pin_mem.c b/mm/pin_mem.c
new file mode 100644
index 0000000..0a143b6
--- /dev/null
+++ b/mm/pin_mem.c
@@ -0,0 +1,950 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved.
+ * Provide the pin memory method for checkpoint and restore task.
+ */
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/sched/cputime.h>
+#include <linux/tick.h>
+#include <linux/mm.h>
+#include <linux/pin_mem.h>
+#include <linux/idr.h>
+#include <linux/page-isolation.h>
+#include <linux/sched/mm.h>
+#include <linux/ctype.h>
+#include <linux/highmem.h>
+#include <crypto/sha.h>
+
+#define MAX_PIN_PID_NUM 128
+static DEFINE_SPINLOCK(page_map_entry_lock);
+
+struct pin_mem_dump_info *pin_mem_dump_start;
+unsigned int pin_pid_num;
+static unsigned int *pin_pid_num_addr;
+static unsigned long __page_map_entry_start;
+static unsigned long page_map_entry_end;
+static struct page_map_info *user_space_reserve_start;
+static struct page_map_entry *page_map_entry_start;
+unsigned int max_pin_pid_num __read_mostly;
+unsigned long redirect_space_size;
+unsigned long redirect_space_start;
+#define DEFAULT_REDIRECT_SPACE_SIZE 0x100000
+
+static int __init setup_max_pin_pid_num(char *str)
+{
+ int ret = 0;
+
+ if (!str)
+ goto out;
+
+ ret = kstrtouint(str, 10, &max_pin_pid_num);
+out:
+ if (ret) {
+ pr_warn("Unable to parse max pin pid num.\n");
+ } else {
+ if (max_pin_pid_num > MAX_PIN_PID_NUM) {
+ max_pin_pid_num = 0;
+ pr_warn("Input max_pin_pid_num is too large.\n");
+ }
+ }
+ return ret;
+}
+early_param("max_pin_pid_num", setup_max_pin_pid_num);
+
+static int __init setup_redirect_space_size(char *str)
+{
+ if (!str)
+ goto out;
+
+ redirect_space_size = memparse(str, NULL);
+out:
+ if (!redirect_space_size) {
+ pr_warn("Unable to parse redirect space size, use the default value.\n");
+ redirect_space_size = DEFAULT_REDIRECT_SPACE_SIZE;
+ }
+ return 0;
+}
+early_param("redirect_space_size", setup_redirect_space_size);
+
+struct page_map_info *create_page_map_info(int pid)
+{
+ struct page_map_info *new;
+
+ if (!user_space_reserve_start)
+ return NULL;
+
+ if (pin_pid_num >= max_pin_pid_num) {
+ pr_warn("Pin pid num too large than max_pin_pid_num, fail create: %d!", pid);
+ return NULL;
+ }
+ new = (struct page_map_info *)(user_space_reserve_start + pin_pid_num);
+ new->pid = pid;
+ new->pme = NULL;
+ new->entry_num = 0;
+ new->pid_reserved = false;
+ new->disable_free_page = false;
+ (*pin_pid_num_addr)++;
+ pin_pid_num++;
+ return new;
+}
+EXPORT_SYMBOL_GPL(create_page_map_info);
+
+struct page_map_info *get_page_map_info(int pid)
+{
+ int i;
+
+ if (!user_space_reserve_start)
+ return NULL;
+
+ for (i = 0; i < pin_pid_num; i++) {
+ if (user_space_reserve_start[i].pid == pid)
+ return &(user_space_reserve_start[i]);
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(get_page_map_info);
+
+static struct page *find_head_page(struct page *page)
+{
+ struct page *p = page;
+
+ while (!PageBuddy(p)) {
+ if (PageLRU(p))
+ return NULL;
+ p--;
+ }
+ return p;
+}
+
+static void spilt_page_area_left(struct zone *zone, struct free_area *area, struct page *page,
+ unsigned long size, int order)
+{
+ unsigned long cur_size = 1 << order;
+ unsigned long total_size = 0;
+
+ while (size && cur_size > size) {
+ cur_size >>= 1;
+ order--;
+ area--;
+ if (cur_size <= size) {
+ list_add(&page[total_size].lru, &area->free_list[MIGRATE_MOVABLE]);
+ atomic_set(&(page[total_size]._mapcount), PAGE_BUDDY_MAPCOUNT_VALUE);
+ set_page_private(&page[total_size], order);
+ set_pageblock_migratetype(&page[total_size], MIGRATE_MOVABLE);
+ area->nr_free++;
+ total_size += cur_size;
+ size -= cur_size;
+ }
+ }
+}
+
+static void spilt_page_area_right(struct zone *zone, struct free_area *area, struct page *page,
+ unsigned long size, int order)
+{
+ unsigned long cur_size = 1 << order;
+ struct page *right_page, *head_page;
+
+ right_page = page + size;
+ while (size && cur_size > size) {
+ cur_size >>= 1;
+ order--;
+ area--;
+ if (cur_size <= size) {
+ head_page = right_page - cur_size;
+ list_add(&head_page->lru, &area->free_list[MIGRATE_MOVABLE]);
+ atomic_set(&(head_page->_mapcount), PAGE_BUDDY_MAPCOUNT_VALUE);
+ set_page_private(head_page, order);
+ set_pageblock_migratetype(head_page, MIGRATE_MOVABLE);
+ area->nr_free++;
+ size -= cur_size;
+ right_page = head_page;
+ }
+ }
+}
+
+void reserve_page_from_buddy(unsigned long nr_pages, struct page *page)
+{
+ unsigned int current_order;
+ struct page *page_end;
+ struct free_area *area;
+ struct zone *zone;
+ struct page *head_page;
+
+ head_page = find_head_page(page);
+ if (!head_page) {
+ pr_warn("Find page head fail.");
+ return;
+ }
+ current_order = head_page->private;
+ page_end = head_page + (1 << current_order);
+ zone = page_zone(head_page);
+ area = &(zone->free_area[current_order]);
+ list_del(&head_page->lru);
+ atomic_set(&head_page->_mapcount, -1);
+ set_page_private(head_page, 0);
+ area->nr_free--;
+ if (head_page != page)
+ spilt_page_area_left(zone, area, head_page,
+ (unsigned long)(page - head_page), current_order);
+ page = page + nr_pages;
+ if (page < page_end) {
+ spilt_page_area_right(zone, area, page,
+ (unsigned long)(page_end - page), current_order);
+ } else if (page > page_end) {
+ pr_warn("Find page end smaller than page.");
+ }
+}
+
+static inline void reserve_user_normal_pages(struct page *page)
+{
+ atomic_inc(&page->_refcount);
+ reserve_page_from_buddy(1, page);
+}
+
+static void init_huge_pmd_pages(struct page *head_page)
+{
+ int i = 0;
+ struct page *page = head_page;
+
+ __set_bit(PG_head, &page->flags);
+ __set_bit(PG_active, &page->flags);
+ atomic_set(&page->_refcount, 1);
+ page++;
+ i++;
+ page->compound_head = (unsigned long)head_page + 1;
+ page->compound_dtor = HUGETLB_PAGE_DTOR + 1;
+ page->compound_order = HPAGE_PMD_ORDER;
+ page++;
+ i++;
+ page->compound_head = (unsigned long)head_page + 1;
+ i++;
+ INIT_LIST_HEAD(&(page->deferred_list));
+ for (; i < HPAGE_PMD_NR; i++) {
+ page = head_page + i;
+ page->compound_head = (unsigned long)head_page + 1;
+ }
+}
+
+static inline void reserve_user_huge_pmd_pages(struct page *page)
+{
+ atomic_inc(&page->_refcount);
+ reserve_page_from_buddy((1 << HPAGE_PMD_ORDER), page);
+ init_huge_pmd_pages(page);
+}
+
+int reserve_user_map_pages_fail;
+
+void free_user_map_pages(unsigned int pid_index, unsigned int entry_index, unsigned int page_index)
+{
+ unsigned int i, j, index, order;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ struct page *page;
+ unsigned long phy_addr;
+
+ for (index = 0; index < pid_index; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ }
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < entry_index; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ for (j = 0; j < page_index; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+}
+
+bool check_redirect_end_valid(struct redirect_info *redirect_start,
+ unsigned long max_redirect_page_num)
+{
+ unsigned long redirect_end;
+
+ redirect_end = ((unsigned long)(redirect_start + 1) +
+ max_redirect_page_num * sizeof(unsigned int));
+ if (redirect_end > redirect_space_start + redirect_space_size)
+ return false;
+ return false;
+}
+
+static void reserve_user_space_map_pages(void)
+{
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ unsigned int i, j, index;
+ struct page *page;
+ unsigned long flags;
+ unsigned long phy_addr;
+ unsigned long redirect_pages = 0;
+ struct redirect_info *redirect_start = (struct redirect_info *)redirect_space_start;
+
+ if (!user_space_reserve_start || !redirect_start)
+ return;
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ redirect_pages = 0;
+ if (!check_redirect_end_valid(redirect_start, pme->nr_pages))
+ redirect_start = NULL;
+ for (j = 0; j < pme->nr_pages; j++) {
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (atomic_read(&page->_refcount)) {
+ if ((page->flags & PAGE_FLAGS_CHECK_RESERVED)
+ && !pme->redirect_start)
+ pme->redirect_start =
+ (unsigned long)redirect_start;
+ if (redirect_start &&
+ (page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ redirect_start->redirect_index[redirect_pages] = j;
+ redirect_pages++;
+ continue;
+ } else {
+ reserve_user_map_pages_fail = 1;
+ pr_warn("Page %pK refcount %d large than zero, no need reserve.\n",
+ page, atomic_read(&page->_refcount));
+ goto free_pages;
+ }
+ }
+ if (!pme->is_huge_page)
+ reserve_user_normal_pages(page);
+ else
+ reserve_user_huge_pmd_pages(page);
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ if (redirect_pages && redirect_start) {
+ redirect_start->redirect_pages = redirect_pages;
+ redirect_start = (struct redirect_info *)(
+ (unsigned long)(redirect_start + 1) +
+ redirect_start->redirect_pages * sizeof(unsigned int));
+ }
+ }
+ }
+ spin_unlock(&page_map_entry_lock);
+ return;
+free_pages:
+ free_user_map_pages(index, i, j);
+ spin_unlock(&page_map_entry_lock);
+}
+
+
+int calculate_pin_mem_digest(struct pin_mem_dump_info *pmdi, char *digest)
+{
+ int i;
+ struct sha256_state sctx;
+
+ if (!digest)
+ digest = pmdi->sha_digest;
+ sha256_init(&sctx);
+ sha256_update(&sctx, (unsigned char *)(&(pmdi->magic)),
+ sizeof(struct pin_mem_dump_info) - SHA256_DIGEST_SIZE);
+ for (i = 0; i < pmdi->pin_pid_num; i++) {
+ sha256_update(&sctx, (unsigned char *)(&(pmdi->pmi_array[i])),
+ sizeof(struct page_map_info));
+ }
+ sha256_final(&sctx, digest);
+ return 0;
+}
+
+static int check_sha_digest(struct pin_mem_dump_info *pmdi)
+{
+ int ret = 0;
+ char digest[SHA256_DIGEST_SIZE] = {0};
+
+ ret = calculate_pin_mem_digest(pmdi, digest);
+ if (ret) {
+ pr_warn("calculate pin mem digest fail:%d\n", ret);
+ return ret;
+ }
+ if (memcmp(pmdi->sha_digest, digest, SHA256_DIGEST_SIZE)) {
+ pr_warn("pin mem dump info sha256 digest match error!\n");
+ return -EFAULT;
+ }
+ return ret;
+}
+
+/*
+ * The whole page map entry collect process must be Sequentially.
+ * The user_space_reserve_start points to the first page map info for
+ * the first dump task. And the page_map_entry_start points to
+ * the first page map entry of the first dump vma.
+ */
+static void init_page_map_info(struct pin_mem_dump_info *pmdi, unsigned long map_len)
+{
+ if (pin_mem_dump_start || !max_pin_pid_num) {
+ pr_warn("pin page map already init or max_pin_pid_num not set.\n");
+ return;
+ }
+ if (map_len < sizeof(struct pin_mem_dump_info) +
+ max_pin_pid_num * sizeof(struct page_map_info) + redirect_space_size) {
+ pr_warn("pin memory reserved memblock too small.\n");
+ return;
+ }
+ if ((pmdi->magic != PIN_MEM_DUMP_MAGIC) || (pmdi->pin_pid_num > max_pin_pid_num) ||
+ check_sha_digest(pmdi))
+ memset(pmdi, 0, sizeof(struct pin_mem_dump_info));
+ pin_mem_dump_start = pmdi;
+ pin_pid_num = pmdi->pin_pid_num;
+ pr_info("pin_pid_num: %d\n", pin_pid_num);
+ pin_pid_num_addr = &(pmdi->pin_pid_num);
+ user_space_reserve_start =
+ (struct page_map_info *)pmdi->pmi_array;
+ page_map_entry_start =
+ (struct page_map_entry *)(user_space_reserve_start + max_pin_pid_num);
+ page_map_entry_end = (unsigned long)pmdi + map_len - redirect_space_size;
+ redirect_space_start = page_map_entry_end;
+ if (pin_pid_num > 0)
+ reserve_user_space_map_pages();
+}
+
+int finish_pin_mem_dump(void)
+{
+ int ret;
+
+ pin_mem_dump_start->magic = PIN_MEM_DUMP_MAGIC;
+ memset(pin_mem_dump_start->sha_digest, 0, SHA256_DIGEST_SIZE);
+ ret = calculate_pin_mem_digest(pin_mem_dump_start, NULL);
+ if (ret) {
+ pr_warn("calculate pin mem digest fail:%d\n", ret);
+ return ret;
+ }
+ return ret;
+}
+
+int collect_pmd_huge_pages(struct task_struct *task,
+ unsigned long start_addr, unsigned long end_addr, struct page_map_entry *pme)
+{
+ long res;
+ int index = 0;
+ unsigned long start = start_addr;
+ struct page *temp_page;
+
+ while (start < end_addr) {
+ temp_page = NULL;
+ res = get_user_pages_remote(task->mm, start, 1,
+ FOLL_TOUCH | FOLL_GET, &temp_page, NULL, NULL);
+ if (!res) {
+ pr_warn("Get huge page for addr(%lx) fail.", start);
+ return COLLECT_PAGES_FAIL;
+ }
+ if (PageHead(temp_page)) {
+ start += HPAGE_PMD_SIZE;
+ pme->phy_addr_array[index] = page_to_phys(temp_page);
+ index++;
+ } else {
+ pme->nr_pages = index;
+ atomic_dec(&((temp_page)->_refcount));
+ return COLLECT_PAGES_NEED_CONTINUE;
+ }
+ }
+ pme->nr_pages = index;
+ return COLLECT_PAGES_FINISH;
+}
+
+int collect_normal_pages(struct task_struct *task,
+ unsigned long start_addr, unsigned long end_addr, struct page_map_entry *pme)
+{
+ int res;
+ unsigned long next;
+ unsigned long i, nr_pages;
+ struct page *tmp_page;
+ unsigned long *phy_addr_array = pme->phy_addr_array;
+ struct page **page_array = (struct page **)pme->phy_addr_array;
+
+ next = (start_addr & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE;
+ next = (next > end_addr) ? end_addr : next;
+ pme->nr_pages = 0;
+ while (start_addr < next) {
+ nr_pages = (PAGE_ALIGN(next) - start_addr) / PAGE_SIZE;
+ res = get_user_pages_remote(task->mm, start_addr, 1,
+ FOLL_TOUCH | FOLL_GET, &tmp_page, NULL, NULL);
+ if (!res) {
+ pr_warn("Get user page of %lx fail.\n", start_addr);
+ return COLLECT_PAGES_FAIL;
+ }
+ if (PageHead(tmp_page)) {
+ atomic_dec(&(tmp_page->_refcount));
+ return COLLECT_PAGES_NEED_CONTINUE;
+ }
+ atomic_dec(&(tmp_page->_refcount));
+ if (PageTail(tmp_page)) {
+ start_addr = next;
+ pme->virt_addr = start_addr;
+ next = (next + HPAGE_PMD_SIZE) > end_addr ?
+ end_addr : (next + HPAGE_PMD_SIZE);
+ continue;
+ }
+ res = get_user_pages_remote(task->mm, start_addr, nr_pages,
+ FOLL_TOUCH | FOLL_GET, page_array, NULL, NULL);
+ if (!res) {
+ pr_warn("Get user pages of %lx fail.\n", start_addr);
+ return COLLECT_PAGES_FAIL;
+ }
+ for (i = 0; i < nr_pages; i++)
+ phy_addr_array[i] = page_to_phys(page_array[i]);
+ pme->nr_pages += nr_pages;
+ page_array += nr_pages;
+ phy_addr_array += nr_pages;
+ start_addr = next;
+ next = (next + HPAGE_PMD_SIZE) > end_addr ? end_addr : (next + HPAGE_PMD_SIZE);
+ }
+ return COLLECT_PAGES_FINISH;
+}
+
+/* Users make sure that the pin memory belongs to anonymous vma. */
+int pin_mem_area(struct task_struct *task, struct mm_struct *mm,
+ unsigned long start_addr, unsigned long end_addr)
+{
+ int pid, ret;
+ int is_huge_page = false;
+ unsigned int page_size;
+ unsigned long nr_pages, flags;
+ struct page_map_entry *pme;
+ struct page_map_info *pmi;
+ struct vm_area_struct *vma;
+ unsigned long i;
+ struct page *tmp_page;
+
+ if (!page_map_entry_start
+ || !task || !mm
+ || start_addr >= end_addr)
+ return -EFAULT;
+
+ pid = task->pid;
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ nr_pages = ((end_addr - start_addr) / PAGE_SIZE);
+ if ((unsigned long)page_map_entry_start + nr_pages * sizeof(struct page *) >=
+ page_map_entry_end) {
+ pr_warn("Page map entry use up!\n");
+ ret = -EFAULT;
+ goto finish;
+ }
+ vma = find_extend_vma(mm, start_addr);
+ if (!vma) {
+ pr_warn("Find no match vma!\n");
+ ret = -EFAULT;
+ goto finish;
+ }
+ if (start_addr == (start_addr & HPAGE_PMD_MASK) &&
+ transparent_hugepage_enabled(vma)) {
+ page_size = HPAGE_PMD_SIZE;
+ is_huge_page = true;
+ } else {
+ page_size = PAGE_SIZE;
+ }
+ pme = page_map_entry_start;
+ pme->virt_addr = start_addr;
+ pme->redirect_start = 0;
+ pme->is_huge_page = is_huge_page;
+ memset(pme->phy_addr_array, 0, nr_pages * sizeof(unsigned long));
+ down_write(&mm->mmap_lock);
+ if (!is_huge_page) {
+ ret = collect_normal_pages(task, start_addr, end_addr, pme);
+ if (ret != COLLECT_PAGES_FAIL && !pme->nr_pages) {
+ if (ret == COLLECT_PAGES_FINISH) {
+ ret = 0;
+ up_write(&mm->mmap_lock);
+ goto finish;
+ }
+ pme->is_huge_page = true;
+ page_size = HPAGE_PMD_SIZE;
+ ret = collect_pmd_huge_pages(task, pme->virt_addr, end_addr, pme);
+ }
+ } else {
+ ret = collect_pmd_huge_pages(task, start_addr, end_addr, pme);
+ if (ret != COLLECT_PAGES_FAIL && !pme->nr_pages) {
+ if (ret == COLLECT_PAGES_FINISH) {
+ ret = 0;
+ up_write(&mm->mmap_lock);
+ goto finish;
+ }
+ pme->is_huge_page = false;
+ page_size = PAGE_SIZE;
+ ret = collect_normal_pages(task, pme->virt_addr, end_addr, pme);
+ }
+ }
+ up_write(&mm->mmap_lock);
+ if (ret == COLLECT_PAGES_FAIL) {
+ ret = -EFAULT;
+ goto finish;
+ }
+
+ /* check for zero pages */
+ for (i = 0; i < pme->nr_pages; i++) {
+ tmp_page = phys_to_page(pme->phy_addr_array[i]);
+ if (!pme->is_huge_page) {
+ if (page_to_pfn(tmp_page) == my_zero_pfn(pme->virt_addr + i * PAGE_SIZE))
+ pme->phy_addr_array[i] = 0;
+ } else if (is_huge_zero_page(tmp_page))
+ pme->phy_addr_array[i] = 0;
+ }
+
+ page_map_entry_start = (struct page_map_entry *)(next_pme(pme));
+ pmi = get_page_map_info(pid);
+ if (!pmi)
+ pmi = create_page_map_info(pid);
+ if (!pmi) {
+ pr_warn("Create page map info fail for pid: %d!\n", pid);
+ ret = -EFAULT;
+ goto finish;
+ }
+ if (!pmi->pme)
+ pmi->pme = pme;
+ pmi->entry_num++;
+ spin_unlock_irqrestore(&page_map_entry_lock, flags);
+ if (ret == COLLECT_PAGES_NEED_CONTINUE)
+ ret = pin_mem_area(task, mm, pme->virt_addr + pme->nr_pages * page_size, end_addr);
+ return ret;
+finish:
+ spin_unlock_irqrestore(&page_map_entry_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pin_mem_area);
+
+vm_fault_t remap_normal_pages(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page_map_entry *pme)
+{
+ int ret;
+ unsigned int j, i;
+ pgd_t *pgd;
+ p4d_t *p4d;
+ pmd_t *pmd;
+ pud_t *pud;
+ struct page *page, *new;
+ unsigned long address;
+ unsigned long phy_addr;
+ unsigned int redirect_pages = 0;
+ struct redirect_info *redirect_start;
+
+ redirect_start = (struct redirect_info *)pme->redirect_start;
+ for (j = 0; j < pme->nr_pages; j++) {
+ address = pme->virt_addr + j * PAGE_SIZE;
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (page_to_pfn(page) == my_zero_pfn(address)) {
+ pme->phy_addr_array[j] = 0;
+ continue;
+ }
+ pme->phy_addr_array[j] = 0;
+ if (redirect_start && (redirect_pages < redirect_start->redirect_pages) &&
+ (j == redirect_start->redirect_index[redirect_pages])) {
+ new = alloc_zeroed_user_highpage_movable(vma, address);
+ if (!new) {
+ pr_warn("Redirect alloc page fail\n");
+ continue;
+ }
+ copy_page(page_to_virt(new), phys_to_virt(phy_addr));
+ page = new;
+ redirect_pages++;
+ }
+ page->mapping = NULL;
+ pgd = pgd_offset(mm, address);
+ p4d = p4d_alloc(mm, pgd, address);
+ if (!p4d) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pud = pud_alloc(mm, p4d, address);
+ if (!pud) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pmd = pmd_alloc(mm, pud, address);
+ if (!pmd) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ ret = do_anon_page_remap(vma, address, pmd, page);
+ if (ret)
+ goto free;
+ }
+ return 0;
+free:
+ for (i = j; i < pme->nr_pages; i++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ __free_page(phys_to_page(phy_addr));
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ return ret;
+}
+
+static inline gfp_t get_hugepage_gfpmask(struct vm_area_struct *vma)
+{
+ const bool vma_madvised = !!(vma->vm_flags & VM_HUGEPAGE);
+
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE | (vma_madvised ? 0 : __GFP_NORETRY);
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM;
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+ __GFP_KSWAPD_RECLAIM);
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+ 0);
+ return GFP_TRANSHUGE_LIGHT;
+}
+
+vm_fault_t remap_huge_pmd_pages(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page_map_entry *pme)
+{
+ int ret;
+ unsigned int j, i;
+ pgd_t *pgd;
+ p4d_t *p4d;
+ pmd_t *pmd;
+ pud_t *pud;
+ gfp_t gfp;
+ struct page *page, *new;
+ unsigned long address;
+ unsigned long phy_addr;
+ unsigned int redirect_pages = 0;
+ struct redirect_info *redirect_start;
+
+ redirect_start = (struct redirect_info *)pme->redirect_start;
+ for (j = 0; j < pme->nr_pages; j++) {
+ address = pme->virt_addr + j * HPAGE_PMD_SIZE;
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (is_huge_zero_page(page)) {
+ pme->phy_addr_array[j] = 0;
+ continue;
+ }
+ pme->phy_addr_array[j] = 0;
+ if (redirect_start && (redirect_pages < redirect_start->redirect_pages) &&
+ (j == redirect_start->redirect_index[redirect_pages])) {
+ gfp = get_hugepage_gfpmask(vma);
+ new = alloc_hugepage_vma(gfp, vma, address, HPAGE_PMD_ORDER);
+ if (!new) {
+ pr_warn("Redirect alloc huge page fail\n");
+ continue;
+ }
+ memcpy(page_to_virt(new), phys_to_virt(phy_addr), HPAGE_PMD_SIZE);
+ page = new;
+ redirect_pages++;
+ }
+ pgd = pgd_offset(mm, address);
+ p4d = p4d_alloc(mm, pgd, address);
+ if (!p4d) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pud = pud_alloc(mm, p4d, address);
+ if (!pud) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pmd = pmd_alloc(mm, pud, address);
+ if (!pmd) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ ret = do_anon_huge_page_remap(vma, address, pmd, page);
+ if (ret)
+ goto free;
+ }
+ return 0;
+free:
+ for (i = j; i < pme->nr_pages; i++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, HPAGE_PMD_ORDER);
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ }
+ return ret;
+}
+
+static void free_unmap_pages(struct page_map_info *pmi,
+ struct page_map_entry *pme,
+ unsigned int index)
+{
+ unsigned int i, j;
+ unsigned long phy_addr;
+ unsigned int order;
+ struct page *page;
+
+ pme = (struct page_map_entry *)(next_pme(pme));
+ for (i = index; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)(next_pme(pme));
+ }
+}
+
+vm_fault_t do_mem_remap(int pid, struct mm_struct *mm)
+{
+ unsigned int i = 0;
+ vm_fault_t ret = 0;
+ struct vm_area_struct *vma;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ unsigned long flags;
+
+ if (reserve_user_map_pages_fail)
+ return -EFAULT;
+ pmi = get_page_map_info(pid);
+ if (!pmi)
+ return -EFAULT;
+
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ pmi->disable_free_page = true;
+ spin_unlock(&page_map_entry_lock);
+ down_write(&mm->mmap_lock);
+ pme = pmi->pme;
+ vma = mm->mmap;
+ while ((i < pmi->entry_num) && (vma != NULL)) {
+ if (pme->virt_addr >= vma->vm_start && pme->virt_addr < vma->vm_end) {
+ i++;
+ if (!vma_is_anonymous(vma)) {
+ pme = (struct page_map_entry *)(next_pme(pme));
+ continue;
+ }
+ if (!pme->is_huge_page) {
+ ret = remap_normal_pages(mm, vma, pme);
+ if (ret < 0)
+ goto free;
+ } else {
+ ret = remap_huge_pmd_pages(mm, vma, pme);
+ if (ret < 0)
+ goto free;
+ }
+ pme = (struct page_map_entry *)(next_pme(pme));
+ } else {
+ vma = vma->vm_next;
+ }
+ }
+ up_write(&mm->mmap_lock);
+ return 0;
+free:
+ free_unmap_pages(pmi, pme, i);
+ up_write(&mm->mmap_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(do_mem_remap);
+
+#if defined(CONFIG_ARM64)
+void init_reserve_page_map(unsigned long map_addr, unsigned long map_size)
+{
+ void *addr;
+
+ if (!map_addr || !map_size)
+ return;
+ addr = phys_to_virt(map_addr);
+ init_page_map_info((struct pin_mem_dump_info *)addr, map_size);
+}
+#else
+void init_reserve_page_map(unsigned long map_addr, unsigned long map_size)
+{
+}
+#endif
+
+static void free_all_reserved_pages(void)
+{
+ unsigned int i, j, index, order;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ struct page *page;
+ unsigned long phy_addr;
+
+ if (!user_space_reserve_start || reserve_user_map_pages_fail)
+ return;
+
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ if (pmi->disable_free_page)
+ continue;
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ }
+}
+
+/* Clear all pin memory record. */
+void clear_pin_memory_record(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ free_all_reserved_pages();
+ if (pin_pid_num_addr) {
+ *pin_pid_num_addr = 0;
+ pin_pid_num = 0;
+ page_map_entry_start = (struct page_map_entry *)__page_map_entry_start;
+ }
+ spin_unlock(&page_map_entry_lock);
+}
+EXPORT_SYMBOL_GPL(clear_pin_memory_record);
+
+#endif /* CONFIG_PIN_MEMORY */
--
2.9.5
2
1
尊敬的linux内核组各位老师同学:
你们好!
我是北京拓林思软件有限公司的员工邓伟进。我对linux内核进程管理,文件系统和
设备驱动有一定理解。熟悉bpf。目前正努力致力于研究学习bpf和linux内核进程管
理,内存管理和文件系统。热爱操作系统和编程。严谨,并喜欢刨根究底的探究问
题。这次在陈琪德老师鼓励下申请加入linux内核组,还望通过!非常感谢,我会
争取能为社区做一些力所能及的工作。
期待您的回复!
邓伟进 2021.3.2
2
1
From: zhuling <zhuling8(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: NA
Enabled e820_pmem in arm64:
Use memmap=nn[KMG]!ss[KMG] reserve memory for persistent storage
when the kernel restart or update. the data in PMEM will not be lost
and can be loaded faster.this is a general features.
if you want use this features, you need do as follows:
1.reserve memory: add memmap to reserve memory in grub.cfg
memmap=nn[KMG]!ss[KMG] exp:memmap=100K!0x1a0000000.
2.insmod nd_e820.ko: modprobe nd_e820.
3.check pmem device in /dev exp: /dev/pmem0.
Signed-off-by: zhuling <zhuling8(a)huawei.com>
---
arch/arm64/Kconfig | 24 ++++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/pmem.c | 35 ++++++++++++++
arch/arm64/kernel/setup.c | 6 +++
arch/arm64/mm/init.c | 98 ++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/Makefile | 1 +
include/linux/mm.h | 4 ++
7 files changed, 169 insertions(+)
create mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b9c56543c..f1e05d9d2 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1141,6 +1141,30 @@ config XEN_DOM0
def_bool y
depends on XEN
+config ARM64_PMEM_LEGACY_DEVICE
+ bool
+
+config ARM64_PMEM_RESERVE
+ bool "reserve memory for persistent storage"
+ default y
+ help
+ Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve memory for
+ persistent storage
+
+ Say y here to enable this feature
+
+config ARM64_PMEM_LEGACY
+ tristate "create persistent storage"
+ depends on ARM64_PMEM_RESERVE
+ depends on BLK_DEV
+ select ARM64_PMEM_LEGACY_DEVICE
+ select LIBNVDIMM
+ help
+ Use reserved memory for persistent storage when the kernel restart
+ or update. the data in PMEM will not be lost and can be loaded faster.
+
+ Say y if unsure.
+
config XEN
bool "Xen guest support on ARM64"
depends on ARM64 && OF
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2621d5c2b..c363639b8 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o
obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_ARM64_MTE) += mte.o
+obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c
new file mode 100644
index 000000000..16eaf706f
--- /dev/null
+++ b/arch/arm64/kernel/pmem.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Derived from x86 and arm64 implement PMEM.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+static int found(struct resource *res, void *data)
+{
+ return 1;
+}
+
+static int __init register_e820_pmem(void)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+ IORESOURCE_MEM, 0, -1, NULL, found);
+ if (rc <= 0)
+ return 0;
+
+ /*
+ * See drivers/nvdimm/e820.c for the implementation, this is
+ * simply here to trigger the module to load on demand.
+ */
+ pdev = platform_device_alloc("e820_pmem", -1);
+
+ return platform_device_add(pdev);
+}
+device_initcall(register_e820_pmem);
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 6aff30de8..7f506036d 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -255,6 +255,12 @@ static void __init request_standard_resources(void)
request_resource(res, &crashk_res);
#endif
}
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ if (pmem_res.end && pmem_res.start)
+ request_resource(&iomem_resource, &pmem_res);
+#endif
+
}
static int __init reserve_memblock_reserved_regions(void)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 794f992cb..e4dc19145 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -63,6 +63,18 @@ EXPORT_SYMBOL(memstart_addr);
phys_addr_t arm64_dma_phys_limit __ro_after_init;
phys_addr_t arm64_dma32_phys_limit __ro_after_init;
+static unsigned long long pmem_size, pmem_start;
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+struct resource pmem_res = {
+ .name = "Persistent Memory (legacy)",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY
+};
+#endif
+
#ifndef CONFIG_KEXEC_CORE
static void __init reserve_crashkernel(void)
{
@@ -236,6 +248,88 @@ static void __init fdt_enforce_memory_region(void)
memblock_add(usable_rgns[1].base, usable_rgns[1].size);
}
+static int __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start)
+{
+ if (!memblock_is_region_memory(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region is not memory!\n");
+ return -EINVAL;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region overlaps reserved memory!\n");
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve mem: base address is not 2MB aligned!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init parse_memmap_one(char *p)
+{
+ char *oldp;
+ phys_addr_t start_at, mem_size;
+ int ret;
+
+ if (!p)
+ return -EINVAL;
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
+
+ if (!mem_size)
+ return -EINVAL;
+
+ mem_size = PAGE_ALIGN(mem_size);
+
+ if (*p == '!') {
+ start_at = memparse(p+1, &p);
+
+ if (is_mem_valid(mem_size, start_at) != 0)
+ return -EINVAL;
+
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ start_at, start_at + mem_size, mem_size >> 20);
+ pmem_start = start_at;
+ pmem_size = mem_size;
+ } else
+ pr_info("Unrecognized memmap option, please check the parameter.\n");
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+ while (str) {
+ char *k = strchr(str, ',');
+
+ if (k)
+ *k++ = 0;
+
+ parse_memmap_one(str);
+ str = k;
+ }
+
+ return 0;
+}
+early_param("memmap", parse_memmap_opt);
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+static void __init reserve_pmem(void)
+{
+ memblock_remove(pmem_start, pmem_size);
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ pmem_start, pmem_start + pmem_size, pmem_size >> 20);
+ pmem_res.start = pmem_start;
+ pmem_res.end = pmem_start + pmem_size - 1;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -359,6 +453,10 @@ void __init arm64_memblock_init(void)
reserve_elfcorehdr();
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ reserve_pmem();
+#endif
+
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
dma_contiguous_reserve(arm64_dma32_phys_limit);
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 29203f3d3..b97760e9f 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_ARM64_PMEM_LEGACY) += nd_e820.o
obj-$(CONFIG_OF_PMEM) += of_pmem.o
obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
diff --git a/include/linux/mm.h b/include/linux/mm.h
index cd5c31372..a5e50495e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -45,6 +45,10 @@ extern int sysctl_page_lock_unfairness;
void init_mm_internals(void);
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+extern struct resource pmem_res;
+#endif
+
#ifndef CONFIG_NEED_MULTIPLE_NODES /* Don't use mapnrs, do it properly */
extern unsigned long max_mapnr;
--
2.19.1
2
1

[PATCH openEuler-21.03 2/2] pid: add pid reserve method for checkpoint and recover
by hejingxian 02 Mar '21
by hejingxian 02 Mar '21
02 Mar '21
From: Jingxian He <hejingxian(a)huawei.com>
Date: Mon, 1 Mar 2021 17:44:59 +0800
Subject: [PATCH openEuler-21.03 2/2] pid: add pid reserve method for checkpoint and recover
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
We record the pid of dump tasks in the reserved memory,
and reserve the pids before init task start.
In the recover process, free the reserved pids and realloc them for use.
Signed-off-by: Jingxian He <hejingxian(a)huawei.com>
Reviewed-by: Wenliang He <hewenliang4(a)huawei.com>
Reviewed-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
---
arch/arm64/configs/openeuler_defconfig | 1 +
include/linux/pin_mem.h | 6 ++++
kernel/pid.c | 10 +++++++
mm/Kconfig | 10 +++++++
mm/pin_mem.c | 51 ++++++++++++++++++++++++++++++++++
5 files changed, 78 insertions(+)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig
index 76fda68..de6db02 100644
--- a/arch/arm64/configs/openeuler_defconfig
+++ b/arch/arm64/configs/openeuler_defconfig
@@ -1037,6 +1037,7 @@ CONFIG_FRAME_VECTOR=y
# CONFIG_READ_ONLY_THP_FOR_FS is not set
CONFIG_ARCH_HAS_PTE_SPECIAL=y
CONFIG_PIN_MEMORY=y
+CONFIG_PID_RESERVE=y
# end of Memory Management options
CONFIG_NET=y
diff --git a/include/linux/pin_mem.h b/include/linux/pin_mem.h
index bc8b03e..a9fe2ef 100644
--- a/include/linux/pin_mem.h
+++ b/include/linux/pin_mem.h
@@ -74,5 +74,11 @@ extern struct resource pin_memory_resource;
#endif
extern void init_reserve_page_map(unsigned long map_addr, unsigned long map_size);
+#ifdef CONFIG_PID_RESERVE
+extern bool is_need_reserve_pids(void);
+extern void free_reserved_pid(struct idr *idr, int pid);
+extern void reserve_pids(struct idr *idr, int pid_max);
+#endif
+
#endif /* CONFIG_PIN_MEMORY */
#endif /* _LINUX_PIN_MEMORY_H */
diff --git a/kernel/pid.c b/kernel/pid.c
index 4856818..32ab9ef 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -44,6 +44,9 @@
#include <linux/idr.h>
#include <net/sock.h>
#include <uapi/linux/pidfd.h>
+#ifdef CONFIG_PID_RESERVE
+#include <linux/pin_mem.h>
+#endif
struct pid init_struct_pid = {
.count = REFCOUNT_INIT(1),
@@ -209,6 +212,9 @@ struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid,
spin_lock_irq(&pidmap_lock);
if (tid) {
+#ifdef CONFIG_PID_RESERVE
+ free_reserved_pid(&tmp->idr, tid);
+#endif
nr = idr_alloc(&tmp->idr, NULL, tid,
tid + 1, GFP_ATOMIC);
/*
@@ -621,6 +627,10 @@ void __init pid_idr_init(void)
init_pid_ns.pid_cachep = KMEM_CACHE(pid,
SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT);
+#ifdef CONFIG_PID_RESERVE
+ if (is_need_reserve_pids())
+ reserve_pids(&init_pid_ns.idr, pid_max);
+#endif
}
static struct file *__pidfd_fget(struct task_struct *task, int fd)
diff --git a/mm/Kconfig b/mm/Kconfig
index 930dc13..e27d2c6 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -868,3 +868,13 @@ config PIN_MEMORY
the corresponding physical pages mapping info in checkpoint,
and remap the physical pages to restore tasks in restore.
endmenu
+
+config PID_RESERVE
+ bool "Support for reserve pid"
+ depends on PIN_MEMORY
+ help
+ Say y here to enable the pid reserved feature for checkpoint.
+ and restore.
+ We record the pid of dump task in the reserve memory,
+ and reserve the pids before init task start. In restore process,
+ free the reserved pids and realloc them for use.
diff --git a/mm/pin_mem.c b/mm/pin_mem.c
index 0a143b6..a040853 100644
--- a/mm/pin_mem.c
+++ b/mm/pin_mem.c
@@ -947,4 +947,55 @@ void clear_pin_memory_record(void)
}
EXPORT_SYMBOL_GPL(clear_pin_memory_record);
+#ifdef CONFIG_PID_RESERVE
+struct idr *reserve_idr;
+
+/* test if there exist pin memory tasks */
+bool is_need_reserve_pids(void)
+{
+ return (pin_pid_num > 0);
+}
+
+void free_reserved_pid(struct idr *idr, int pid)
+{
+ unsigned int index;
+ struct page_map_info *pmi;
+
+ if (!max_pin_pid_num || idr != reserve_idr)
+ return;
+
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ if (pmi->pid == pid && pmi->pid_reserved) {
+ idr_remove(idr, pid);
+ return;
+ }
+ }
+}
+
+/* reserve pids for check point tasks which pinned memory */
+void reserve_pids(struct idr *idr, int pid_max)
+{
+ int alloc_pid;
+ unsigned int index;
+ struct page_map_info *pmi;
+
+ if (!max_pin_pid_num)
+ return;
+ reserve_idr = idr;
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pmi->pid_reserved = true;
+ alloc_pid = idr_alloc(idr, NULL, pmi->pid, pid_max, GFP_ATOMIC);
+ if (alloc_pid != pmi->pid) {
+ if (alloc_pid > 0)
+ idr_remove(idr, alloc_pid);
+ pr_warn("Reserve pid (%d) fail, real pid is %d.\n", alloc_pid, pmi->pid);
+ pmi->pid_reserved = false;
+ continue;
+ }
+ }
+}
+#endif /* CONFIG_PID_RESERVE */
+
#endif /* CONFIG_PIN_MEMORY */
--
2.9.5
1
0

[PATCH openEuler-21.03 1/2] mm: add pin memory method for checkpoint add restore
by hejingxian@huawei.com 02 Mar '21
by hejingxian@huawei.com 02 Mar '21
02 Mar '21
From: Jingxian He <hejingxian(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
We can use the checkpoint and restore in userspace(criu) method to
dump and restore tasks when updating the kernel.
Currently, criu needs dump all memory data of tasks to files.
When the memory size is very large(larger than 1G),
the cost time of the dumping data will be very long(more than 1 min).
By pin the memory data of tasks and collect the corresponding
physical pages mapping info in checkpoint process,
we can remap the physical pages to restore tasks after
upgrading the kernel. This pin memory method can
restore the task data within one second.
The pin memory area info is saved in the reserved memblock,
which can keep usable in the kernel update process.
The pin memory driver provides the following ioctl command for criu:
1) SET_PIN_MEM_AREA:
Set pin memory area, which can be remap to the restore task.
2) CLEAR_PIN_MEM_AREA:
Clear the pin memory area info,
which enable user reset the pin data.
3) REMAP_PIN_MEM_AREA:
Remap the pages of the pin memory to the restore task.
Signed-off-by: Jingxian He <hejingxian(a)huawei.com>
Reviewed-by: Wenliang He <hewenliang4(a)huawei.com>
Reviewed-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
---
arch/arm64/configs/openeuler_defconfig | 2 +
arch/arm64/kernel/setup.c | 9 +
arch/arm64/mm/init.c | 60 +++
drivers/char/Kconfig | 6 +
drivers/char/Makefile | 1 +
drivers/char/pin_memory.c | 208 ++++++++
include/linux/crash_core.h | 5 +
include/linux/pin_mem.h | 78 +++
kernel/crash_core.c | 11 +
mm/Kconfig | 8 +
mm/Makefile | 1 +
mm/huge_memory.c | 61 +++
mm/memory.c | 59 ++
mm/pin_mem.c | 950 +++++++++++++++++++++++++++++++++
14 files changed, 1459 insertions(+)
create mode 100644 drivers/char/pin_memory.c
create mode 100644 include/linux/pin_mem.h
create mode 100644 mm/pin_mem.c
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig
index c5271e7..76fda68 100644
--- a/arch/arm64/configs/openeuler_defconfig
+++ b/arch/arm64/configs/openeuler_defconfig
@@ -1036,6 +1036,7 @@ CONFIG_FRAME_VECTOR=y
# CONFIG_GUP_BENCHMARK is not set
# CONFIG_READ_ONLY_THP_FOR_FS is not set
CONFIG_ARCH_HAS_PTE_SPECIAL=y
+CONFIG_PIN_MEMORY=y
# end of Memory Management options
CONFIG_NET=y
@@ -3282,6 +3283,7 @@ CONFIG_TCG_TIS_ST33ZP24_SPI=y
# CONFIG_RANDOM_TRUST_CPU is not set
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
+CONFIG_PIN_MEMORY_DEV=m
#
# I2C support
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index c1f1fb9..5e282d3 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -50,6 +50,9 @@
#include <asm/efi.h>
#include <asm/xen/hypervisor.h>
#include <asm/mmu_context.h>
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/pin_mem.h>
+#endif
static int num_standard_resources;
static struct resource *standard_resources;
@@ -260,6 +263,12 @@ static void __init request_standard_resources(void)
quick_kexec_res.end <= res->end)
request_resource(res, &quick_kexec_res);
#endif
+#ifdef CONFIG_PIN_MEMORY
+ if (pin_memory_resource.end &&
+ pin_memory_resource.start >= res->start &&
+ pin_memory_resource.end <= res->end)
+ request_resource(res, &pin_memory_resource);
+#endif
}
}
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f3e5a66..8ab5aac 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -42,6 +42,9 @@
#include <linux/sizes.h>
#include <asm/tlb.h>
#include <asm/alternative.h>
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/pin_mem.h>
+#endif
#define ARM64_ZONE_DMA_BITS 30
@@ -78,6 +81,55 @@ static void __init reserve_crashkernel(void)
*/
#define MAX_USABLE_RANGES 2
+#ifdef CONFIG_PIN_MEMORY
+struct resource pin_memory_resource = {
+ .name = "Pin memory",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_RESERVED
+};
+
+static void __init reserve_pin_memory_res(void)
+{
+ unsigned long long mem_start, mem_len;
+ int ret;
+
+ ret = parse_pin_memory(boot_command_line, memblock_phys_mem_size(),
+ &mem_len, &mem_start);
+ if (ret || !mem_len)
+ return;
+
+ mem_len = PAGE_ALIGN(mem_len);
+
+ if (!memblock_is_region_memory(mem_start, mem_len)) {
+ pr_warn("cannot reserve for pin memory: region is not memory!\n");
+ return;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_len)) {
+ pr_warn("cannot reserve for pin memory: region overlaps reserved memory!\n");
+ return;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve for pin memory: base address is not 2MB aligned\n");
+ return;
+ }
+
+ memblock_reserve(mem_start, mem_len);
+ pr_debug("pin memory resource reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ mem_start, mem_start + mem_len, mem_len >> 20);
+
+ pin_memory_resource.start = mem_start;
+ pin_memory_resource.end = mem_start + mem_len - 1;
+}
+#else
+static void __init reserve_pin_memory_res(void)
+{
+}
+#endif /* CONFIG_PIN_MEMORY */
+
#ifdef CONFIG_CRASH_DUMP
static int __init early_init_dt_scan_elfcorehdr(unsigned long node,
const char *uname, int depth, void *data)
@@ -455,6 +507,8 @@ void __init arm64_memblock_init(void)
reserve_park_mem();
#endif
+ reserve_pin_memory_res();
+
reserve_elfcorehdr();
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
@@ -583,6 +637,12 @@ void __init mem_init(void)
/* this will put all unused low memory onto the freelists */
memblock_free_all();
+#ifdef CONFIG_PIN_MEMORY
+ /* pre alloc the pages for pin memory */
+ init_reserve_page_map((unsigned long)pin_memory_resource.start,
+ (unsigned long)(pin_memory_resource.end - pin_memory_resource.start + 1));
+#endif
+
mem_init_print_info(NULL);
/*
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index d229a2d..fbb94b8 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -496,3 +496,9 @@ config RANDOM_TRUST_BOOTLOADER
booloader is trustworthy so it will be added to the kernel's entropy
pool. Otherwise, say N here so it will be regarded as device input that
only mixes the entropy pool.
+
+config PIN_MEMORY_DEV
+ bool "/dev/pinmem character device"
+ default m
+ help
+ pin memory driver
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index ffce287..71d76fd 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
obj-$(CONFIG_XILLYBUS) += xillybus/
obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
obj-$(CONFIG_ADI) += adi.o
+obj-$(CONFIG_PIN_MEMORY_DEV) += pin_memory.o
diff --git a/drivers/char/pin_memory.c b/drivers/char/pin_memory.c
new file mode 100644
index 0000000..f46e056
--- /dev/null
+++ b/drivers/char/pin_memory.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright @ Huawei Technologies Co., Ltd. 2020-2020. ALL rights reserved.
+ * Description: Euler pin memory driver
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/mm_types.h>
+#include <linux/processor.h>
+#include <uapi/asm-generic/ioctl.h>
+#include <uapi/asm-generic/mman-common.h>
+#include <uapi/asm/setup.h>
+#include <linux/pin_mem.h>
+#include <linux/sched/mm.h>
+
+#define MAX_PIN_MEM_AREA_NUM 16
+struct _pin_mem_area {
+ unsigned long virt_start;
+ unsigned long virt_end;
+};
+
+struct pin_mem_area_set {
+ unsigned int pid;
+ unsigned int area_num;
+ struct _pin_mem_area mem_area[MAX_PIN_MEM_AREA_NUM];
+};
+
+#define PIN_MEM_MAGIC 0x59
+#define _SET_PIN_MEM_AREA 1
+#define _CLEAR_PIN_MEM_AREA 2
+#define _REMAP_PIN_MEM_AREA 3
+#define _FINISH_PIN_MEM_DUMP 4
+#define _PIN_MEM_IOC_MAX_NR 4
+#define SET_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _SET_PIN_MEM_AREA, struct pin_mem_area_set)
+#define CLEAR_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _CLEAR_PIN_MEM_AREA, int)
+#define REMAP_PIN_MEM_AREA _IOW(PIN_MEM_MAGIC, _REMAP_PIN_MEM_AREA, int)
+#define FINISH_PIN_MEM_DUMP _IOW(PIN_MEM_MAGIC, _FINISH_PIN_MEM_DUMP, int)
+static int set_pin_mem(struct pin_mem_area_set *pmas)
+{
+ int i;
+ int ret = 0;
+ struct _pin_mem_area *pma;
+ struct mm_struct *mm;
+ struct task_struct *task;
+ struct pid *pid_s;
+
+ pid_s = find_get_pid(pmas->pid);
+ if (!pid_s) {
+ pr_warn("Get pid struct fail:%d.\n", pmas->pid);
+ return -EFAULT;
+ }
+ rcu_read_lock();
+ task = pid_task(pid_s, PIDTYPE_PID);
+ if (!task) {
+ pr_warn("Get task struct fail:%d.\n", pmas->pid);
+ goto fail;
+ }
+ mm = get_task_mm(task);
+ for (i = 0; i < pmas->area_num; i++) {
+ pma = &(pmas->mem_area[i]);
+ ret = pin_mem_area(task, mm, pma->virt_start, pma->virt_end);
+ if (ret) {
+ mmput(mm);
+ goto fail;
+ }
+ }
+ mmput(mm);
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return ret;
+
+fail:
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return -EFAULT;
+}
+
+static int set_pin_mem_area(unsigned long arg)
+{
+ struct pin_mem_area_set pmas;
+ void __user *buf = (void __user *)arg;
+
+ if (!access_ok(buf, sizeof(pmas)))
+ return -EFAULT;
+ if (copy_from_user(&pmas, buf, sizeof(pmas)))
+ return -EINVAL;
+ if (pmas.area_num > MAX_PIN_MEM_AREA_NUM) {
+ pr_warn("Input area_num is too large.\n");
+ return -EINVAL;
+ }
+
+ return set_pin_mem(&pmas);
+}
+
+static int pin_mem_remap(unsigned long arg)
+{
+ int pid;
+ struct task_struct *task;
+ struct mm_struct *mm;
+ vm_fault_t ret;
+ void __user *buf = (void __user *)arg;
+ struct pid *pid_s;
+
+ if (!access_ok(buf, sizeof(int)))
+ return -EINVAL;
+ if (copy_from_user(&pid, buf, sizeof(int)))
+ return -EINVAL;
+
+ pid_s = find_get_pid(pid);
+ if (!pid_s) {
+ pr_warn("Get pid struct fail:%d.\n", pid);
+ return -EINVAL;
+ }
+ rcu_read_lock();
+ task = pid_task(pid_s, PIDTYPE_PID);
+ if (!task) {
+ pr_warn("Get task struct fail:%d.\n", pid);
+ goto fault;
+ }
+ mm = get_task_mm(task);
+ ret = do_mem_remap(pid, mm);
+ if (ret) {
+ pr_warn("Handle pin memory remap fail.\n");
+ mmput(mm);
+ goto fault;
+ }
+ mmput(mm);
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return 0;
+
+fault:
+ rcu_read_unlock();
+ put_pid(pid_s);
+ return -EFAULT;
+}
+
+static long pin_memory_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long ret = 0;
+
+ if (_IOC_TYPE(cmd) != PIN_MEM_MAGIC)
+ return -EINVAL;
+ if (_IOC_NR(cmd) > _PIN_MEM_IOC_MAX_NR)
+ return -EINVAL;
+
+ switch (cmd) {
+ case SET_PIN_MEM_AREA:
+ ret = set_pin_mem_area(arg);
+ break;
+ case CLEAR_PIN_MEM_AREA:
+ clear_pin_memory_record();
+ break;
+ case REMAP_PIN_MEM_AREA:
+ ret = pin_mem_remap(arg);
+ break;
+ case FINISH_PIN_MEM_DUMP:
+ ret = finish_pin_mem_dump();
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static const struct file_operations pin_memory_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = pin_memory_ioctl,
+ .compat_ioctl = pin_memory_ioctl,
+};
+
+static struct miscdevice pin_memory_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "pinmem",
+ .fops = &pin_memory_fops,
+};
+
+static int pin_memory_init(void)
+{
+ int err = misc_register(&pin_memory_miscdev);
+
+ if (!err)
+ pr_info("pin_memory init\n");
+ else
+ pr_warn("pin_memory init failed!\n");
+ return err;
+}
+
+static void pin_memory_exit(void)
+{
+ misc_deregister(&pin_memory_miscdev);
+ pr_info("pin_memory ko exists!\n");
+}
+
+module_init(pin_memory_init);
+module_exit(pin_memory_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Euler");
+MODULE_DESCRIPTION("pin memory");
diff --git a/include/linux/crash_core.h b/include/linux/crash_core.h
index fc0ef33..30f0df3 100644
--- a/include/linux/crash_core.h
+++ b/include/linux/crash_core.h
@@ -87,4 +87,9 @@ int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
unsigned long long *crash_size, unsigned long long *crash_base);
+#ifdef CONFIG_PIN_MEMORY
+int __init parse_pin_memory(char *cmdline, unsigned long long system_ram,
+ unsigned long long *pin_size, unsigned long long *pin_base);
+#endif
+
#endif /* LINUX_CRASH_CORE_H */
diff --git a/include/linux/pin_mem.h b/include/linux/pin_mem.h
new file mode 100644
index 0000000..bc8b03e
--- /dev/null
+++ b/include/linux/pin_mem.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved.
+ * Provide the pin memory method for check point and restore task.
+ */
+#ifndef _LINUX_PIN_MEMORY_H
+#define _LINUX_PIN_MEMORY_H
+
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/errno.h>
+#include <linux/mm_types.h>
+#include <linux/err.h>
+#ifdef CONFIG_ARM64
+#include <linux/ioport.h>
+#endif
+
+#define PAGE_BUDDY_MAPCOUNT_VALUE (~PG_buddy)
+
+#define COLLECT_PAGES_FINISH 0
+#define COLLECT_PAGES_NEED_CONTINUE 1
+#define COLLECT_PAGES_FAIL -1
+
+#define COMPOUND_PAD_MASK 0xffffffff
+#define COMPOUND_PAD_START 0x88
+#define COMPOUND_PAD_DELTA 0x40
+#define LIST_POISON4 0xdead000000000400
+#define PAGE_FLAGS_CHECK_RESERVED (1UL << PG_reserved)
+#define SHA256_DIGEST_SIZE 32
+#define next_pme(pme) ((unsigned long *)(pme + 1) + pme->nr_pages)
+#define PIN_MEM_DUMP_MAGIC 0xfeab000000001acd
+struct page_map_entry {
+ unsigned long virt_addr;
+ unsigned int nr_pages;
+ unsigned int is_huge_page;
+ unsigned long redirect_start;
+ unsigned long phy_addr_array[0];
+};
+
+struct page_map_info {
+ int pid;
+ int pid_reserved;
+ unsigned int entry_num;
+ int disable_free_page;
+ struct page_map_entry *pme;
+};
+
+struct pin_mem_dump_info {
+ char sha_digest[SHA256_DIGEST_SIZE];
+ unsigned long magic;
+ unsigned int pin_pid_num;
+ struct page_map_info pmi_array[0];
+};
+
+struct redirect_info {
+ unsigned int redirect_pages;
+ unsigned int redirect_index[0];
+};
+
+extern struct page_map_info *get_page_map_info(int pid);
+extern struct page_map_info *create_page_map_info(int pid);
+extern vm_fault_t do_mem_remap(int pid, struct mm_struct *mm);
+extern vm_fault_t do_anon_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page);
+extern void clear_pin_memory_record(void);
+extern int pin_mem_area(struct task_struct *task, struct mm_struct *mm,
+ unsigned long start_addr, unsigned long end_addr);
+extern vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page);
+extern int finish_pin_mem_dump(void);
+
+/* reserve space for pin memory*/
+#ifdef CONFIG_ARM64
+extern struct resource pin_memory_resource;
+#endif
+extern void init_reserve_page_map(unsigned long map_addr, unsigned long map_size);
+
+#endif /* CONFIG_PIN_MEMORY */
+#endif /* _LINUX_PIN_MEMORY_H */
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index bfed474..2407de3 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -450,6 +450,17 @@ void __init reserve_crashkernel(void)
}
#endif /* CONFIG_ARCH_WANT_RESERVE_CRASH_KERNEL */
+#ifdef CONFIG_PIN_MEMORY
+int __init parse_pin_memory(char *cmdline,
+ unsigned long long system_ram,
+ unsigned long long *pin_size,
+ unsigned long long *pin_base)
+{
+ return __parse_crashkernel(cmdline, system_ram, pin_size, pin_base,
+ "pinmemory=", NULL);
+}
+#endif
+
Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
void *data, size_t data_len)
{
diff --git a/mm/Kconfig b/mm/Kconfig
index 390165f..930dc13 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -859,4 +859,12 @@ config ARCH_HAS_HUGEPD
config MAPPING_DIRTY_HELPERS
bool
+config PIN_MEMORY
+ bool "Support for pin memory"
+ depends on CHECKPOINT_RESTORE
+ help
+ Say y here to enable the pin memory feature for checkpoint
+ and restore. We can pin the memory data of tasks and collect
+ the corresponding physical pages mapping info in checkpoint,
+ and remap the physical pages to restore tasks in restore.
endmenu
diff --git a/mm/Makefile b/mm/Makefile
index d73aed0..4963827 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -120,3 +120,4 @@ obj-$(CONFIG_MEMFD_CREATE) += memfd.o
obj-$(CONFIG_MAPPING_DIRTY_HELPERS) += mapping_dirty_helpers.o
obj-$(CONFIG_PTDUMP_CORE) += ptdump.o
obj-$(CONFIG_PAGE_REPORTING) += page_reporting.o
+obj-$(CONFIG_PIN_MEMORY) += pin_mem.o
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 0bc4a2c..8a11d30 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2996,3 +2996,64 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new)
update_mmu_cache_pmd(vma, address, pvmw->pmd);
}
#endif
+
+#ifdef CONFIG_PIN_MEMORY
+vm_fault_t do_anon_huge_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page)
+{
+ gfp_t gfp;
+ pgtable_t pgtable;
+ spinlock_t *ptl;
+ pmd_t entry;
+ vm_fault_t ret = 0;
+
+ if (unlikely(anon_vma_prepare(vma)))
+ return VM_FAULT_OOM;
+ if (unlikely(khugepaged_enter(vma, vma->vm_flags)))
+ return VM_FAULT_OOM;
+ gfp = alloc_hugepage_direct_gfpmask(vma);
+ prep_transhuge_page(page);
+ if (mem_cgroup_charge(page, vma->vm_mm, gfp)) {
+ put_page(page);
+ count_vm_event(THP_FAULT_FALLBACK);
+ count_vm_event(THP_FAULT_FALLBACK_CHARGE);
+ return VM_FAULT_FALLBACK;
+ }
+ cgroup_throttle_swaprate(page, gfp);
+
+ pgtable = pte_alloc_one(vma->vm_mm);
+ if (unlikely(!pgtable)) {
+ ret = VM_FAULT_OOM;
+ goto release;
+ }
+ __SetPageUptodate(page);
+ ptl = pmd_lock(vma->vm_mm, pmd);
+ if (unlikely(!pmd_none(*pmd))) {
+ goto unlock_release;
+ } else {
+ ret = check_stable_address_space(vma->vm_mm);
+ if (ret)
+ goto unlock_release;
+ entry = mk_huge_pmd(page, vma->vm_page_prot);
+ entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
+ page_add_new_anon_rmap(page, vma, address, true);
+ lru_cache_add_inactive_or_unevictable(page, vma);
+ pgtable_trans_huge_deposit(vma->vm_mm, pmd, pgtable);
+ set_pmd_at(vma->vm_mm, address, pmd, entry);
+ add_mm_counter(vma->vm_mm, MM_ANONPAGES, HPAGE_PMD_NR);
+ mm_inc_nr_ptes(vma->vm_mm);
+ spin_unlock(ptl);
+ count_vm_event(THP_FAULT_ALLOC);
+ count_memcg_event_mm(vma->vm_mm, THP_FAULT_ALLOC);
+ }
+
+ return 0;
+unlock_release:
+ spin_unlock(ptl);
+release:
+ if (pgtable)
+ pte_free(vma->vm_mm, pgtable);
+ put_page(page);
+ return ret;
+}
+#endif
diff --git a/mm/memory.c b/mm/memory.c
index 50632c4..7b7f1a7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -5248,3 +5248,62 @@ void ptlock_free(struct page *page)
kmem_cache_free(page_ptl_cachep, page->ptl);
}
#endif
+
+#ifdef CONFIG_PIN_MEMORY
+vm_fault_t do_anon_page_remap(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmd, struct page *page)
+{
+ pte_t entry;
+ spinlock_t *ptl;
+ pte_t *pte;
+ vm_fault_t ret = 0;
+
+ if (pte_alloc(vma->vm_mm, pmd))
+ return VM_FAULT_OOM;
+
+ /* See the comment in pte_alloc_one_map() */
+ if (unlikely(pmd_trans_unstable(pmd)))
+ return 0;
+
+ /* Allocate our own private page. */
+ if (unlikely(anon_vma_prepare(vma)))
+ goto oom;
+
+ if (mem_cgroup_charge(page, vma->vm_mm, GFP_KERNEL))
+ goto oom_free_page;
+ cgroup_throttle_swaprate(page, GFP_KERNEL);
+
+ __SetPageUptodate(page);
+
+ entry = mk_pte(page, vma->vm_page_prot);
+ if (vma->vm_flags & VM_WRITE)
+ entry = pte_mkwrite(pte_mkdirty(entry));
+ pte = pte_offset_map_lock(vma->vm_mm, pmd, address,
+ &ptl);
+ if (!pte_none(*pte)) {
+ ret = VM_FAULT_FALLBACK;
+ goto release;
+ }
+
+ ret = check_stable_address_space(vma->vm_mm);
+ if (ret)
+ goto release;
+ inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
+ page_add_new_anon_rmap(page, vma, address, false);
+ lru_cache_add_inactive_or_unevictable(page, vma);
+
+ set_pte_at(vma->vm_mm, address, pte, entry);
+ /* No need to invalidate - it was non-present before */
+ update_mmu_cache(vma, address, pte);
+unlock:
+ pte_unmap_unlock(pte, ptl);
+ return ret;
+release:
+ put_page(page);
+ goto unlock;
+oom_free_page:
+ put_page(page);
+oom:
+ return VM_FAULT_OOM;
+}
+#endif
diff --git a/mm/pin_mem.c b/mm/pin_mem.c
new file mode 100644
index 0000000..0a143b6
--- /dev/null
+++ b/mm/pin_mem.c
@@ -0,0 +1,950 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved.
+ * Provide the pin memory method for check point and restore task.
+ */
+#ifdef CONFIG_PIN_MEMORY
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/sched/cputime.h>
+#include <linux/tick.h>
+#include <linux/mm.h>
+#include <linux/pin_mem.h>
+#include <linux/idr.h>
+#include <linux/page-isolation.h>
+#include <linux/sched/mm.h>
+#include <linux/ctype.h>
+#include <linux/highmem.h>
+#include <crypto/sha.h>
+
+#define MAX_PIN_PID_NUM 128
+static DEFINE_SPINLOCK(page_map_entry_lock);
+
+struct pin_mem_dump_info *pin_mem_dump_start;
+unsigned int pin_pid_num;
+static unsigned int *pin_pid_num_addr;
+static unsigned long __page_map_entry_start;
+static unsigned long page_map_entry_end;
+static struct page_map_info *user_space_reserve_start;
+static struct page_map_entry *page_map_entry_start;
+unsigned int max_pin_pid_num __read_mostly;
+unsigned long redirect_space_size;
+unsigned long redirect_space_start;
+#define DEFAULT_REDIRECT_SPACE_SIZE 0x100000
+
+static int __init setup_max_pin_pid_num(char *str)
+{
+ int ret = 0;
+
+ if (!str)
+ goto out;
+
+ ret = kstrtouint(str, 10, &max_pin_pid_num);
+out:
+ if (ret) {
+ pr_warn("Unable to parse max pin pid num.\n");
+ } else {
+ if (max_pin_pid_num > MAX_PIN_PID_NUM) {
+ max_pin_pid_num = 0;
+ pr_warn("Input max_pin_pid_num is too large.\n");
+ }
+ }
+ return ret;
+}
+early_param("max_pin_pid_num", setup_max_pin_pid_num);
+
+static int __init setup_redirect_space_size(char *str)
+{
+ if (!str)
+ goto out;
+
+ redirect_space_size = memparse(str, NULL);
+out:
+ if (!redirect_space_size) {
+ pr_warn("Unable to parse redirect space size, use the default value.\n");
+ redirect_space_size = DEFAULT_REDIRECT_SPACE_SIZE;
+ }
+ return 0;
+}
+early_param("redirect_space_size", setup_redirect_space_size);
+
+struct page_map_info *create_page_map_info(int pid)
+{
+ struct page_map_info *new;
+
+ if (!user_space_reserve_start)
+ return NULL;
+
+ if (pin_pid_num >= max_pin_pid_num) {
+ pr_warn("Pin pid num too large than max_pin_pid_num, fail create: %d!", pid);
+ return NULL;
+ }
+ new = (struct page_map_info *)(user_space_reserve_start + pin_pid_num);
+ new->pid = pid;
+ new->pme = NULL;
+ new->entry_num = 0;
+ new->pid_reserved = false;
+ new->disable_free_page = false;
+ (*pin_pid_num_addr)++;
+ pin_pid_num++;
+ return new;
+}
+EXPORT_SYMBOL_GPL(create_page_map_info);
+
+struct page_map_info *get_page_map_info(int pid)
+{
+ int i;
+
+ if (!user_space_reserve_start)
+ return NULL;
+
+ for (i = 0; i < pin_pid_num; i++) {
+ if (user_space_reserve_start[i].pid == pid)
+ return &(user_space_reserve_start[i]);
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(get_page_map_info);
+
+static struct page *find_head_page(struct page *page)
+{
+ struct page *p = page;
+
+ while (!PageBuddy(p)) {
+ if (PageLRU(p))
+ return NULL;
+ p--;
+ }
+ return p;
+}
+
+static void spilt_page_area_left(struct zone *zone, struct free_area *area, struct page *page,
+ unsigned long size, int order)
+{
+ unsigned long cur_size = 1 << order;
+ unsigned long total_size = 0;
+
+ while (size && cur_size > size) {
+ cur_size >>= 1;
+ order--;
+ area--;
+ if (cur_size <= size) {
+ list_add(&page[total_size].lru, &area->free_list[MIGRATE_MOVABLE]);
+ atomic_set(&(page[total_size]._mapcount), PAGE_BUDDY_MAPCOUNT_VALUE);
+ set_page_private(&page[total_size], order);
+ set_pageblock_migratetype(&page[total_size], MIGRATE_MOVABLE);
+ area->nr_free++;
+ total_size += cur_size;
+ size -= cur_size;
+ }
+ }
+}
+
+static void spilt_page_area_right(struct zone *zone, struct free_area *area, struct page *page,
+ unsigned long size, int order)
+{
+ unsigned long cur_size = 1 << order;
+ struct page *right_page, *head_page;
+
+ right_page = page + size;
+ while (size && cur_size > size) {
+ cur_size >>= 1;
+ order--;
+ area--;
+ if (cur_size <= size) {
+ head_page = right_page - cur_size;
+ list_add(&head_page->lru, &area->free_list[MIGRATE_MOVABLE]);
+ atomic_set(&(head_page->_mapcount), PAGE_BUDDY_MAPCOUNT_VALUE);
+ set_page_private(head_page, order);
+ set_pageblock_migratetype(head_page, MIGRATE_MOVABLE);
+ area->nr_free++;
+ size -= cur_size;
+ right_page = head_page;
+ }
+ }
+}
+
+void reserve_page_from_buddy(unsigned long nr_pages, struct page *page)
+{
+ unsigned int current_order;
+ struct page *page_end;
+ struct free_area *area;
+ struct zone *zone;
+ struct page *head_page;
+
+ head_page = find_head_page(page);
+ if (!head_page) {
+ pr_warn("Find page head fail.");
+ return;
+ }
+ current_order = head_page->private;
+ page_end = head_page + (1 << current_order);
+ zone = page_zone(head_page);
+ area = &(zone->free_area[current_order]);
+ list_del(&head_page->lru);
+ atomic_set(&head_page->_mapcount, -1);
+ set_page_private(head_page, 0);
+ area->nr_free--;
+ if (head_page != page)
+ spilt_page_area_left(zone, area, head_page,
+ (unsigned long)(page - head_page), current_order);
+ page = page + nr_pages;
+ if (page < page_end) {
+ spilt_page_area_right(zone, area, page,
+ (unsigned long)(page_end - page), current_order);
+ } else if (page > page_end) {
+ pr_warn("Find page end smaller than page.");
+ }
+}
+
+static inline void reserve_user_normal_pages(struct page *page)
+{
+ atomic_inc(&page->_refcount);
+ reserve_page_from_buddy(1, page);
+}
+
+static void init_huge_pmd_pages(struct page *head_page)
+{
+ int i = 0;
+ struct page *page = head_page;
+
+ __set_bit(PG_head, &page->flags);
+ __set_bit(PG_active, &page->flags);
+ atomic_set(&page->_refcount, 1);
+ page++;
+ i++;
+ page->compound_head = (unsigned long)head_page + 1;
+ page->compound_dtor = HUGETLB_PAGE_DTOR + 1;
+ page->compound_order = HPAGE_PMD_ORDER;
+ page++;
+ i++;
+ page->compound_head = (unsigned long)head_page + 1;
+ i++;
+ INIT_LIST_HEAD(&(page->deferred_list));
+ for (; i < HPAGE_PMD_NR; i++) {
+ page = head_page + i;
+ page->compound_head = (unsigned long)head_page + 1;
+ }
+}
+
+static inline void reserve_user_huge_pmd_pages(struct page *page)
+{
+ atomic_inc(&page->_refcount);
+ reserve_page_from_buddy((1 << HPAGE_PMD_ORDER), page);
+ init_huge_pmd_pages(page);
+}
+
+int reserve_user_map_pages_fail;
+
+void free_user_map_pages(unsigned int pid_index, unsigned int entry_index, unsigned int page_index)
+{
+ unsigned int i, j, index, order;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ struct page *page;
+ unsigned long phy_addr;
+
+ for (index = 0; index < pid_index; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ }
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < entry_index; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ for (j = 0; j < page_index; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+}
+
+bool check_redirect_end_valid(struct redirect_info *redirect_start,
+ unsigned long max_redirect_page_num)
+{
+ unsigned long redirect_end;
+
+ redirect_end = ((unsigned long)(redirect_start + 1) +
+ max_redirect_page_num * sizeof(unsigned int));
+ if (redirect_end > redirect_space_start + redirect_space_size)
+ return false;
+ return false;
+}
+
+static void reserve_user_space_map_pages(void)
+{
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ unsigned int i, j, index;
+ struct page *page;
+ unsigned long flags;
+ unsigned long phy_addr;
+ unsigned long redirect_pages = 0;
+ struct redirect_info *redirect_start = (struct redirect_info *)redirect_space_start;
+
+ if (!user_space_reserve_start || !redirect_start)
+ return;
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ redirect_pages = 0;
+ if (!check_redirect_end_valid(redirect_start, pme->nr_pages))
+ redirect_start = NULL;
+ for (j = 0; j < pme->nr_pages; j++) {
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (atomic_read(&page->_refcount)) {
+ if ((page->flags & PAGE_FLAGS_CHECK_RESERVED)
+ && !pme->redirect_start)
+ pme->redirect_start =
+ (unsigned long)redirect_start;
+ if (redirect_start &&
+ (page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ redirect_start->redirect_index[redirect_pages] = j;
+ redirect_pages++;
+ continue;
+ } else {
+ reserve_user_map_pages_fail = 1;
+ pr_warn("Page %pK refcount %d large than zero, no need reserve.\n",
+ page, atomic_read(&page->_refcount));
+ goto free_pages;
+ }
+ }
+ if (!pme->is_huge_page)
+ reserve_user_normal_pages(page);
+ else
+ reserve_user_huge_pmd_pages(page);
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ if (redirect_pages && redirect_start) {
+ redirect_start->redirect_pages = redirect_pages;
+ redirect_start = (struct redirect_info *)(
+ (unsigned long)(redirect_start + 1) +
+ redirect_start->redirect_pages * sizeof(unsigned int));
+ }
+ }
+ }
+ spin_unlock(&page_map_entry_lock);
+ return;
+free_pages:
+ free_user_map_pages(index, i, j);
+ spin_unlock(&page_map_entry_lock);
+}
+
+
+int calculate_pin_mem_digest(struct pin_mem_dump_info *pmdi, char *digest)
+{
+ int i;
+ struct sha256_state sctx;
+
+ if (!digest)
+ digest = pmdi->sha_digest;
+ sha256_init(&sctx);
+ sha256_update(&sctx, (unsigned char *)(&(pmdi->magic)),
+ sizeof(struct pin_mem_dump_info) - SHA256_DIGEST_SIZE);
+ for (i = 0; i < pmdi->pin_pid_num; i++) {
+ sha256_update(&sctx, (unsigned char *)(&(pmdi->pmi_array[i])),
+ sizeof(struct page_map_info));
+ }
+ sha256_final(&sctx, digest);
+ return 0;
+}
+
+static int check_sha_digest(struct pin_mem_dump_info *pmdi)
+{
+ int ret = 0;
+ char digest[SHA256_DIGEST_SIZE] = {0};
+
+ ret = calculate_pin_mem_digest(pmdi, digest);
+ if (ret) {
+ pr_warn("calculate pin mem digest fail:%d\n", ret);
+ return ret;
+ }
+ if (memcmp(pmdi->sha_digest, digest, SHA256_DIGEST_SIZE)) {
+ pr_warn("pin mem dump info sha256 digest match error!\n");
+ return -EFAULT;
+ }
+ return ret;
+}
+
+/*
+ * The whole page map entry collect process must be Sequentially.
+ * The user_space_reserve_start points to the first page map info for
+ * the first dump task. And the page_map_entry_start points to
+ * the first page map entry of the first dump vma.
+ */
+static void init_page_map_info(struct pin_mem_dump_info *pmdi, unsigned long map_len)
+{
+ if (pin_mem_dump_start || !max_pin_pid_num) {
+ pr_warn("pin page map already init or max_pin_pid_num not set.\n");
+ return;
+ }
+ if (map_len < sizeof(struct pin_mem_dump_info) +
+ max_pin_pid_num * sizeof(struct page_map_info) + redirect_space_size) {
+ pr_warn("pin memory reserved memblock too small.\n");
+ return;
+ }
+ if ((pmdi->magic != PIN_MEM_DUMP_MAGIC) || (pmdi->pin_pid_num > max_pin_pid_num) ||
+ check_sha_digest(pmdi))
+ memset(pmdi, 0, sizeof(struct pin_mem_dump_info));
+ pin_mem_dump_start = pmdi;
+ pin_pid_num = pmdi->pin_pid_num;
+ pr_info("pin_pid_num: %d\n", pin_pid_num);
+ pin_pid_num_addr = &(pmdi->pin_pid_num);
+ user_space_reserve_start =
+ (struct page_map_info *)pmdi->pmi_array;
+ page_map_entry_start =
+ (struct page_map_entry *)(user_space_reserve_start + max_pin_pid_num);
+ page_map_entry_end = (unsigned long)pmdi + map_len - redirect_space_size;
+ redirect_space_start = page_map_entry_end;
+ if (pin_pid_num > 0)
+ reserve_user_space_map_pages();
+}
+
+int finish_pin_mem_dump(void)
+{
+ int ret;
+
+ pin_mem_dump_start->magic = PIN_MEM_DUMP_MAGIC;
+ memset(pin_mem_dump_start->sha_digest, 0, SHA256_DIGEST_SIZE);
+ ret = calculate_pin_mem_digest(pin_mem_dump_start, NULL);
+ if (ret) {
+ pr_warn("calculate pin mem digest fail:%d\n", ret);
+ return ret;
+ }
+ return ret;
+}
+
+int collect_pmd_huge_pages(struct task_struct *task,
+ unsigned long start_addr, unsigned long end_addr, struct page_map_entry *pme)
+{
+ long res;
+ int index = 0;
+ unsigned long start = start_addr;
+ struct page *temp_page;
+
+ while (start < end_addr) {
+ temp_page = NULL;
+ res = get_user_pages_remote(task->mm, start, 1,
+ FOLL_TOUCH | FOLL_GET, &temp_page, NULL, NULL);
+ if (!res) {
+ pr_warn("Get huge page for addr(%lx) fail.", start);
+ return COLLECT_PAGES_FAIL;
+ }
+ if (PageHead(temp_page)) {
+ start += HPAGE_PMD_SIZE;
+ pme->phy_addr_array[index] = page_to_phys(temp_page);
+ index++;
+ } else {
+ pme->nr_pages = index;
+ atomic_dec(&((temp_page)->_refcount));
+ return COLLECT_PAGES_NEED_CONTINUE;
+ }
+ }
+ pme->nr_pages = index;
+ return COLLECT_PAGES_FINISH;
+}
+
+int collect_normal_pages(struct task_struct *task,
+ unsigned long start_addr, unsigned long end_addr, struct page_map_entry *pme)
+{
+ int res;
+ unsigned long next;
+ unsigned long i, nr_pages;
+ struct page *tmp_page;
+ unsigned long *phy_addr_array = pme->phy_addr_array;
+ struct page **page_array = (struct page **)pme->phy_addr_array;
+
+ next = (start_addr & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE;
+ next = (next > end_addr) ? end_addr : next;
+ pme->nr_pages = 0;
+ while (start_addr < next) {
+ nr_pages = (PAGE_ALIGN(next) - start_addr) / PAGE_SIZE;
+ res = get_user_pages_remote(task->mm, start_addr, 1,
+ FOLL_TOUCH | FOLL_GET, &tmp_page, NULL, NULL);
+ if (!res) {
+ pr_warn("Get user page of %lx fail.\n", start_addr);
+ return COLLECT_PAGES_FAIL;
+ }
+ if (PageHead(tmp_page)) {
+ atomic_dec(&(tmp_page->_refcount));
+ return COLLECT_PAGES_NEED_CONTINUE;
+ }
+ atomic_dec(&(tmp_page->_refcount));
+ if (PageTail(tmp_page)) {
+ start_addr = next;
+ pme->virt_addr = start_addr;
+ next = (next + HPAGE_PMD_SIZE) > end_addr ?
+ end_addr : (next + HPAGE_PMD_SIZE);
+ continue;
+ }
+ res = get_user_pages_remote(task->mm, start_addr, nr_pages,
+ FOLL_TOUCH | FOLL_GET, page_array, NULL, NULL);
+ if (!res) {
+ pr_warn("Get user pages of %lx fail.\n", start_addr);
+ return COLLECT_PAGES_FAIL;
+ }
+ for (i = 0; i < nr_pages; i++)
+ phy_addr_array[i] = page_to_phys(page_array[i]);
+ pme->nr_pages += nr_pages;
+ page_array += nr_pages;
+ phy_addr_array += nr_pages;
+ start_addr = next;
+ next = (next + HPAGE_PMD_SIZE) > end_addr ? end_addr : (next + HPAGE_PMD_SIZE);
+ }
+ return COLLECT_PAGES_FINISH;
+}
+
+/* Users make sure that the pin memory belongs to anonymous vma. */
+int pin_mem_area(struct task_struct *task, struct mm_struct *mm,
+ unsigned long start_addr, unsigned long end_addr)
+{
+ int pid, ret;
+ int is_huge_page = false;
+ unsigned int page_size;
+ unsigned long nr_pages, flags;
+ struct page_map_entry *pme;
+ struct page_map_info *pmi;
+ struct vm_area_struct *vma;
+ unsigned long i;
+ struct page *tmp_page;
+
+ if (!page_map_entry_start
+ || !task || !mm
+ || start_addr >= end_addr)
+ return -EFAULT;
+
+ pid = task->pid;
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ nr_pages = ((end_addr - start_addr) / PAGE_SIZE);
+ if ((unsigned long)page_map_entry_start + nr_pages * sizeof(struct page *) >=
+ page_map_entry_end) {
+ pr_warn("Page map entry use up!\n");
+ ret = -EFAULT;
+ goto finish;
+ }
+ vma = find_extend_vma(mm, start_addr);
+ if (!vma) {
+ pr_warn("Find no match vma!\n");
+ ret = -EFAULT;
+ goto finish;
+ }
+ if (start_addr == (start_addr & HPAGE_PMD_MASK) &&
+ transparent_hugepage_enabled(vma)) {
+ page_size = HPAGE_PMD_SIZE;
+ is_huge_page = true;
+ } else {
+ page_size = PAGE_SIZE;
+ }
+ pme = page_map_entry_start;
+ pme->virt_addr = start_addr;
+ pme->redirect_start = 0;
+ pme->is_huge_page = is_huge_page;
+ memset(pme->phy_addr_array, 0, nr_pages * sizeof(unsigned long));
+ down_write(&mm->mmap_lock);
+ if (!is_huge_page) {
+ ret = collect_normal_pages(task, start_addr, end_addr, pme);
+ if (ret != COLLECT_PAGES_FAIL && !pme->nr_pages) {
+ if (ret == COLLECT_PAGES_FINISH) {
+ ret = 0;
+ up_write(&mm->mmap_lock);
+ goto finish;
+ }
+ pme->is_huge_page = true;
+ page_size = HPAGE_PMD_SIZE;
+ ret = collect_pmd_huge_pages(task, pme->virt_addr, end_addr, pme);
+ }
+ } else {
+ ret = collect_pmd_huge_pages(task, start_addr, end_addr, pme);
+ if (ret != COLLECT_PAGES_FAIL && !pme->nr_pages) {
+ if (ret == COLLECT_PAGES_FINISH) {
+ ret = 0;
+ up_write(&mm->mmap_lock);
+ goto finish;
+ }
+ pme->is_huge_page = false;
+ page_size = PAGE_SIZE;
+ ret = collect_normal_pages(task, pme->virt_addr, end_addr, pme);
+ }
+ }
+ up_write(&mm->mmap_lock);
+ if (ret == COLLECT_PAGES_FAIL) {
+ ret = -EFAULT;
+ goto finish;
+ }
+
+ /* check for zero pages */
+ for (i = 0; i < pme->nr_pages; i++) {
+ tmp_page = phys_to_page(pme->phy_addr_array[i]);
+ if (!pme->is_huge_page) {
+ if (page_to_pfn(tmp_page) == my_zero_pfn(pme->virt_addr + i * PAGE_SIZE))
+ pme->phy_addr_array[i] = 0;
+ } else if (is_huge_zero_page(tmp_page))
+ pme->phy_addr_array[i] = 0;
+ }
+
+ page_map_entry_start = (struct page_map_entry *)(next_pme(pme));
+ pmi = get_page_map_info(pid);
+ if (!pmi)
+ pmi = create_page_map_info(pid);
+ if (!pmi) {
+ pr_warn("Create page map info fail for pid: %d!\n", pid);
+ ret = -EFAULT;
+ goto finish;
+ }
+ if (!pmi->pme)
+ pmi->pme = pme;
+ pmi->entry_num++;
+ spin_unlock_irqrestore(&page_map_entry_lock, flags);
+ if (ret == COLLECT_PAGES_NEED_CONTINUE)
+ ret = pin_mem_area(task, mm, pme->virt_addr + pme->nr_pages * page_size, end_addr);
+ return ret;
+finish:
+ spin_unlock_irqrestore(&page_map_entry_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pin_mem_area);
+
+vm_fault_t remap_normal_pages(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page_map_entry *pme)
+{
+ int ret;
+ unsigned int j, i;
+ pgd_t *pgd;
+ p4d_t *p4d;
+ pmd_t *pmd;
+ pud_t *pud;
+ struct page *page, *new;
+ unsigned long address;
+ unsigned long phy_addr;
+ unsigned int redirect_pages = 0;
+ struct redirect_info *redirect_start;
+
+ redirect_start = (struct redirect_info *)pme->redirect_start;
+ for (j = 0; j < pme->nr_pages; j++) {
+ address = pme->virt_addr + j * PAGE_SIZE;
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (page_to_pfn(page) == my_zero_pfn(address)) {
+ pme->phy_addr_array[j] = 0;
+ continue;
+ }
+ pme->phy_addr_array[j] = 0;
+ if (redirect_start && (redirect_pages < redirect_start->redirect_pages) &&
+ (j == redirect_start->redirect_index[redirect_pages])) {
+ new = alloc_zeroed_user_highpage_movable(vma, address);
+ if (!new) {
+ pr_warn("Redirect alloc page fail\n");
+ continue;
+ }
+ copy_page(page_to_virt(new), phys_to_virt(phy_addr));
+ page = new;
+ redirect_pages++;
+ }
+ page->mapping = NULL;
+ pgd = pgd_offset(mm, address);
+ p4d = p4d_alloc(mm, pgd, address);
+ if (!p4d) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pud = pud_alloc(mm, p4d, address);
+ if (!pud) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pmd = pmd_alloc(mm, pud, address);
+ if (!pmd) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ ret = do_anon_page_remap(vma, address, pmd, page);
+ if (ret)
+ goto free;
+ }
+ return 0;
+free:
+ for (i = j; i < pme->nr_pages; i++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ __free_page(phys_to_page(phy_addr));
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ return ret;
+}
+
+static inline gfp_t get_hugepage_gfpmask(struct vm_area_struct *vma)
+{
+ const bool vma_madvised = !!(vma->vm_flags & VM_HUGEPAGE);
+
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE | (vma_madvised ? 0 : __GFP_NORETRY);
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM;
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+ __GFP_KSWAPD_RECLAIM);
+ if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags))
+ return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+ 0);
+ return GFP_TRANSHUGE_LIGHT;
+}
+
+vm_fault_t remap_huge_pmd_pages(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page_map_entry *pme)
+{
+ int ret;
+ unsigned int j, i;
+ pgd_t *pgd;
+ p4d_t *p4d;
+ pmd_t *pmd;
+ pud_t *pud;
+ gfp_t gfp;
+ struct page *page, *new;
+ unsigned long address;
+ unsigned long phy_addr;
+ unsigned int redirect_pages = 0;
+ struct redirect_info *redirect_start;
+
+ redirect_start = (struct redirect_info *)pme->redirect_start;
+ for (j = 0; j < pme->nr_pages; j++) {
+ address = pme->virt_addr + j * HPAGE_PMD_SIZE;
+ phy_addr = pme->phy_addr_array[j];
+ if (!phy_addr)
+ continue;
+ page = phys_to_page(phy_addr);
+ if (is_huge_zero_page(page)) {
+ pme->phy_addr_array[j] = 0;
+ continue;
+ }
+ pme->phy_addr_array[j] = 0;
+ if (redirect_start && (redirect_pages < redirect_start->redirect_pages) &&
+ (j == redirect_start->redirect_index[redirect_pages])) {
+ gfp = get_hugepage_gfpmask(vma);
+ new = alloc_hugepage_vma(gfp, vma, address, HPAGE_PMD_ORDER);
+ if (!new) {
+ pr_warn("Redirect alloc huge page fail\n");
+ continue;
+ }
+ memcpy(page_to_virt(new), phys_to_virt(phy_addr), HPAGE_PMD_SIZE);
+ page = new;
+ redirect_pages++;
+ }
+ pgd = pgd_offset(mm, address);
+ p4d = p4d_alloc(mm, pgd, address);
+ if (!p4d) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pud = pud_alloc(mm, p4d, address);
+ if (!pud) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ pmd = pmd_alloc(mm, pud, address);
+ if (!pmd) {
+ ret = VM_FAULT_OOM;
+ goto free;
+ }
+ ret = do_anon_huge_page_remap(vma, address, pmd, page);
+ if (ret)
+ goto free;
+ }
+ return 0;
+free:
+ for (i = j; i < pme->nr_pages; i++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, HPAGE_PMD_ORDER);
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ }
+ return ret;
+}
+
+static void free_unmap_pages(struct page_map_info *pmi,
+ struct page_map_entry *pme,
+ unsigned int index)
+{
+ unsigned int i, j;
+ unsigned long phy_addr;
+ unsigned int order;
+ struct page *page;
+
+ pme = (struct page_map_entry *)(next_pme(pme));
+ for (i = index; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ phy_addr = pme->phy_addr_array[i];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[i] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)(next_pme(pme));
+ }
+}
+
+vm_fault_t do_mem_remap(int pid, struct mm_struct *mm)
+{
+ unsigned int i = 0;
+ vm_fault_t ret = 0;
+ struct vm_area_struct *vma;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ unsigned long flags;
+
+ if (reserve_user_map_pages_fail)
+ return -EFAULT;
+ pmi = get_page_map_info(pid);
+ if (!pmi)
+ return -EFAULT;
+
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ pmi->disable_free_page = true;
+ spin_unlock(&page_map_entry_lock);
+ down_write(&mm->mmap_lock);
+ pme = pmi->pme;
+ vma = mm->mmap;
+ while ((i < pmi->entry_num) && (vma != NULL)) {
+ if (pme->virt_addr >= vma->vm_start && pme->virt_addr < vma->vm_end) {
+ i++;
+ if (!vma_is_anonymous(vma)) {
+ pme = (struct page_map_entry *)(next_pme(pme));
+ continue;
+ }
+ if (!pme->is_huge_page) {
+ ret = remap_normal_pages(mm, vma, pme);
+ if (ret < 0)
+ goto free;
+ } else {
+ ret = remap_huge_pmd_pages(mm, vma, pme);
+ if (ret < 0)
+ goto free;
+ }
+ pme = (struct page_map_entry *)(next_pme(pme));
+ } else {
+ vma = vma->vm_next;
+ }
+ }
+ up_write(&mm->mmap_lock);
+ return 0;
+free:
+ free_unmap_pages(pmi, pme, i);
+ up_write(&mm->mmap_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(do_mem_remap);
+
+#if defined(CONFIG_ARM64)
+void init_reserve_page_map(unsigned long map_addr, unsigned long map_size)
+{
+ void *addr;
+
+ if (!map_addr || !map_size)
+ return;
+ addr = phys_to_virt(map_addr);
+ init_page_map_info((struct pin_mem_dump_info *)addr, map_size);
+}
+#else
+void init_reserve_page_map(unsigned long map_addr, unsigned long map_size)
+{
+}
+#endif
+
+static void free_all_reserved_pages(void)
+{
+ unsigned int i, j, index, order;
+ struct page_map_info *pmi;
+ struct page_map_entry *pme;
+ struct page *page;
+ unsigned long phy_addr;
+
+ if (!user_space_reserve_start || reserve_user_map_pages_fail)
+ return;
+
+ for (index = 0; index < pin_pid_num; index++) {
+ pmi = &(user_space_reserve_start[index]);
+ if (pmi->disable_free_page)
+ continue;
+ pme = pmi->pme;
+ for (i = 0; i < pmi->entry_num; i++) {
+ for (j = 0; j < pme->nr_pages; j++) {
+ order = pme->is_huge_page ? HPAGE_PMD_ORDER : 0;
+ phy_addr = pme->phy_addr_array[j];
+ if (phy_addr) {
+ page = phys_to_page(phy_addr);
+ if (!(page->flags & PAGE_FLAGS_CHECK_RESERVED)) {
+ __free_pages(page, order);
+ pme->phy_addr_array[j] = 0;
+ }
+ }
+ }
+ pme = (struct page_map_entry *)next_pme(pme);
+ }
+ }
+}
+
+/* Clear all pin memory record. */
+void clear_pin_memory_record(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&page_map_entry_lock, flags);
+ free_all_reserved_pages();
+ if (pin_pid_num_addr) {
+ *pin_pid_num_addr = 0;
+ pin_pid_num = 0;
+ page_map_entry_start = (struct page_map_entry *)__page_map_entry_start;
+ }
+ spin_unlock(&page_map_entry_lock);
+}
+EXPORT_SYMBOL_GPL(clear_pin_memory_record);
+
+#endif /* CONFIG_PIN_MEMORY */
--
2.9.5
1
1

[PATCH OLK-5.10 v1] arm64: Declare var of local_cpu_stop only on PARK
by sangyan@huawei.com 01 Mar '21
by sangyan@huawei.com 01 Mar '21
01 Mar '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
Fix compile warning: unused variable 'ops' 'cpu'
while CONFIG_ARM64_CPU_PARK=n.
Put declaration of 'ops' and 'cpu' under
CONFIG_ARM64_CPU_PARK in local_cpu_stop.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/arm64/kernel/smp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 644bbd7..d7b750a 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -1024,8 +1024,10 @@ void arch_irq_work_raise(void)
static void local_cpu_stop(void)
{
+#ifdef CONFIG_ARM64_CPU_PARK
int cpu;
const struct cpu_operations *ops = NULL;
+#endif
set_cpu_online(smp_processor_id(), false);
--
2.9.5
1
0

26 Feb '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
Introducing a feature of CPU PARK in order to save time
of cpus down and up during kexec, which may cost 250ms of
per cpu's down and 30ms of up.
As a result, for 128 cores, it costs more than 30 seconds
to down and up cpus during kexec. Think about 256 cores and more.
CPU PARK is a state that cpu power-on and staying in spin loop, polling
for exit chances, such as writing exit address.
Reserving a block of memory, to fill with cpu park text section,
exit address and park-magic-flag of each cpu. In implementation,
reserved one page for one cpu core.
Cpus going to park state instead of down in machine_shutdown().
Cpus going out of park state in smp_init instead of brought up.
One of cpu park sections in pre-reserved memory blocks,:
+--------------+
+ exit address +
+--------------+
+ park magic +
+--------------+
+ park codes +
+ . +
+ . +
+ . +
+--------------+
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
Reviewed-by: Jing Xiangfeng <jingxiangfeng(a)huawei.com>
---
arch/arm64/Kconfig | 12 ++
arch/arm64/include/asm/kexec.h | 6 +
arch/arm64/include/asm/smp.h | 15 +++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/cpu-park.S | 59 ++++++++++
arch/arm64/kernel/machine_kexec.c | 2 +-
arch/arm64/kernel/process.c | 4 +
arch/arm64/kernel/smp.c | 230 ++++++++++++++++++++++++++++++++++++++
arch/arm64/mm/init.c | 55 +++++++++
9 files changed, 383 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/cpu-park.S
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b9c5654..0885668 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -345,6 +345,18 @@ config KASAN_SHADOW_OFFSET
default 0xeffffff900000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
default 0xffffffffffffffff
+config ARM64_CPU_PARK
+ bool "Support CPU PARK on kexec"
+ depends on SMP
+ depends on KEXEC_CORE
+ help
+ This enables support for CPU PARK feature in
+ order to save time of cpu down to up.
+ CPU park is a state through kexec, spin loop
+ instead of cpu die before jumping to new kernel,
+ jumping out from loop to new kernel entry in
+ smp_init.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 79909ae..a133889 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -36,6 +36,11 @@
#define CRASH_ADDR_HIGH_MAX MEMBLOCK_ALLOC_ACCESSIBLE
+#ifdef CONFIG_ARM64_CPU_PARK
+/* CPU park state flag: "park" */
+#define PARK_MAGIC 0x7061726b
+#endif
+
#ifndef __ASSEMBLY__
/**
@@ -104,6 +109,7 @@ static inline void crash_post_resume(void) {}
#ifdef CONFIG_KEXEC_CORE
extern void __init reserve_crashkernel(void);
#endif
+void machine_kexec_mask_interrupts(void);
#ifdef CONFIG_KEXEC_FILE
#define ARCH_HAS_KIMAGE_ARCH
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 2e7f529..8c5d2d6 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -145,6 +145,21 @@ bool cpus_are_stuck_in_kernel(void);
extern void crash_smp_send_stop(void);
extern bool smp_crash_stop_failed(void);
+#ifdef CONFIG_ARM64_CPU_PARK
+#define PARK_SECTION_SIZE 1024
+struct cpu_park_info {
+ /* Physical address of reserved park memory. */
+ unsigned long start;
+ /* park reserve mem len should be PARK_SECTION_SIZE * NR_CPUS */
+ unsigned long len;
+ /* Virtual address of reserved park memory. */
+ unsigned long start_v;
+};
+extern struct cpu_park_info park_info;
+extern void enter_cpu_park(unsigned long text, unsigned long exit);
+extern void do_cpu_park(unsigned long exit);
+extern int kexec_smp_send_park(void);
+#endif
#endif /* ifndef __ASSEMBLY__ */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2621d5c..60478d2 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o
obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o \
cpu-reset.o
+obj-$(CONFIG_ARM64_CPU_PARK) += cpu-park.o
obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_image.o
obj-$(CONFIG_ARM64_RELOC_TEST) += arm64-reloc-test.o
arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o
diff --git a/arch/arm64/kernel/cpu-park.S b/arch/arm64/kernel/cpu-park.S
new file mode 100644
index 0000000..10c685c
--- /dev/null
+++ b/arch/arm64/kernel/cpu-park.S
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * CPU park routines
+ *
+ * Copyright (C) 2020 Huawei Technologies., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/kexec.h>
+#include <asm/sysreg.h>
+#include <asm/virt.h>
+
+.text
+.pushsection .idmap.text, "awx"
+
+/* cpu park helper in idmap section */
+SYM_CODE_START(enter_cpu_park)
+ /* Clear sctlr_el1 flags. */
+ mrs x12, sctlr_el1
+ mov_q x13, SCTLR_ELx_FLAGS
+ bic x12, x12, x13
+ pre_disable_mmu_workaround
+ msr sctlr_el1, x12 /* disable mmu */
+ isb
+
+ mov x18, x0
+ mov x0, x1 /* secondary_entry addr */
+ br x18 /* call do_cpu_park of each cpu */
+SYM_CODE_END(enter_cpu_park)
+
+.popsection
+
+SYM_CODE_START(do_cpu_park)
+ ldr x18, =PARK_MAGIC /* magic number "park" */
+ add x1, x0, #8
+ str x18, [x1] /* set on-park flag */
+ dc civac, x1 /* flush cache of "park" */
+ dsb nsh
+ isb
+
+.Lloop:
+ wfe
+ isb
+ ldr x19, [x0]
+ cmp x19, #0 /* test secondary_entry */
+ b.eq .Lloop
+
+ ic iallu /* invalidate the local I-cache */
+ dsb nsh
+ isb
+
+ br x19 /* jump to secondary_entry */
+SYM_CODE_END(do_cpu_park)
+
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index a0b144c..f47ce96 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -213,7 +213,7 @@ void machine_kexec(struct kimage *kimage)
BUG(); /* Should never get here. */
}
-static void machine_kexec_mask_interrupts(void)
+void machine_kexec_mask_interrupts(void)
{
unsigned int i;
struct irq_desc *desc;
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 73e3b32..10cffee 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -146,6 +146,10 @@ void arch_cpu_idle_dead(void)
*/
void machine_shutdown(void)
{
+#ifdef CONFIG_ARM64_CPU_PARK
+ if (kexec_smp_send_park() == 0)
+ return;
+#endif
smp_shutdown_nonboot_cpus(reboot_cpu);
}
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 18e9727..dea67d0 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -32,6 +32,7 @@
#include <linux/irq_work.h>
#include <linux/kernel_stat.h>
#include <linux/kexec.h>
+
#include <linux/kvm_host.h>
#include <asm/alternative.h>
@@ -93,6 +94,167 @@ static inline int op_cpu_kill(unsigned int cpu)
}
#endif
+#ifdef CONFIG_ARM64_CPU_PARK
+struct cpu_park_section {
+ unsigned long exit; /* exit address of park look */
+ unsigned long magic; /* maigc represent park state */
+ char text[0]; /* text section of park */
+};
+
+static int mmap_cpu_park_mem(void)
+{
+ if (!park_info.start)
+ return -ENOMEM;
+
+ if (park_info.start_v)
+ return 0;
+
+ park_info.start_v = (unsigned long)__ioremap(park_info.start,
+ park_info.len,
+ PAGE_KERNEL_EXEC);
+ if (!park_info.start_v) {
+ pr_warn("map park memory failed.");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static inline unsigned long cpu_park_section_v(unsigned int cpu)
+{
+ return park_info.start_v + PARK_SECTION_SIZE * (cpu - 1);
+}
+
+static inline unsigned long cpu_park_section_p(unsigned int cpu)
+{
+ return park_info.start + PARK_SECTION_SIZE * (cpu - 1);
+}
+
+/*
+ * Write the secondary_entry to exit section of park state.
+ * Then the secondary cpu will jump straight into the kernel
+ * by the secondary_entry.
+ */
+static int write_park_exit(unsigned int cpu)
+{
+ struct cpu_park_section *park_section;
+ unsigned long *park_exit;
+ unsigned long *park_text;
+
+ if (mmap_cpu_park_mem() != 0)
+ return -EPERM;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ park_exit = &park_section->exit;
+ park_text = (unsigned long *)park_section->text;
+ pr_debug("park_text 0x%lx : 0x%lx, do_cpu_park text 0x%lx : 0x%lx",
+ (unsigned long)park_text, *park_text,
+ (unsigned long)do_cpu_park,
+ *(unsigned long *)do_cpu_park);
+
+ /*
+ * Test first 8 bytes to determine
+ * whether needs to write cpu park exit.
+ */
+ if (*park_text == *(unsigned long *)do_cpu_park) {
+ writeq_relaxed(__pa_symbol(secondary_entry), park_exit);
+ __flush_dcache_area((__force void *)park_exit,
+ sizeof(unsigned long));
+ flush_icache_range((unsigned long)park_exit,
+ (unsigned long)(park_exit + 1));
+ sev();
+ dsb(sy);
+ isb();
+
+ pr_debug("Write cpu %u secondary entry 0x%lx to 0x%lx.",
+ cpu, *park_exit, (unsigned long)park_exit);
+ pr_info("Boot cpu %u from PARK state.", cpu);
+ return 0;
+ }
+
+ return -EPERM;
+}
+
+/* Install cpu park sections for the specific cpu. */
+static int install_cpu_park(unsigned int cpu)
+{
+ struct cpu_park_section *park_section;
+ unsigned long *park_exit;
+ unsigned long *park_magic;
+ unsigned long park_text_len;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ pr_debug("Install cpu park on cpu %u park exit 0x%lx park text 0x%lx",
+ cpu, (unsigned long)park_section,
+ (unsigned long)(park_section->text));
+
+ park_exit = &park_section->exit;
+ park_magic = &park_section->magic;
+ park_text_len = PARK_SECTION_SIZE - sizeof(struct cpu_park_section);
+
+ *park_exit = 0UL;
+ *park_magic = 0UL;
+ memcpy((void *)park_section->text, do_cpu_park, park_text_len);
+ __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE);
+
+ return 0;
+}
+
+static int uninstall_cpu_park(unsigned int cpu)
+{
+ unsigned long park_section;
+
+ if (mmap_cpu_park_mem() != 0)
+ return -EPERM;
+
+ park_section = cpu_park_section_v(cpu);
+ memset((void *)park_section, 0, PARK_SECTION_SIZE);
+ __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE);
+
+ return 0;
+}
+
+static int cpu_wait_park(unsigned int cpu)
+{
+ long timeout;
+ struct cpu_park_section *park_section;
+
+ volatile unsigned long *park_magic;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ park_magic = &park_section->magic;
+
+ timeout = USEC_PER_SEC;
+ while (*park_magic != PARK_MAGIC && timeout--)
+ udelay(1);
+
+ if (timeout > 0)
+ pr_debug("cpu %u park done.", cpu);
+ else
+ pr_err("cpu %u park failed.", cpu);
+
+ return *park_magic == PARK_MAGIC;
+}
+
+static void cpu_park(unsigned int cpu)
+{
+ unsigned long park_section_p;
+ unsigned long park_exit_phy;
+ unsigned long do_park;
+ typeof(enter_cpu_park) *park;
+
+ park_section_p = cpu_park_section_p(cpu);
+ park_exit_phy = park_section_p;
+ pr_debug("Go to park cpu %u exit address 0x%lx", cpu, park_exit_phy);
+
+ do_park = park_section_p + sizeof(struct cpu_park_section);
+ park = (void *)__pa_symbol(enter_cpu_park);
+
+ cpu_install_idmap();
+ park(do_park, park_exit_phy);
+ unreachable();
+}
+#endif
/*
* Boot a secondary CPU, and assign it the specified idle task.
@@ -102,6 +264,10 @@ static int boot_secondary(unsigned int cpu, struct task_struct *idle)
{
const struct cpu_operations *ops = get_cpu_ops(cpu);
+#ifdef CONFIG_ARM64_CPU_PARK
+ if (write_park_exit(cpu) == 0)
+ return 0;
+#endif
if (ops->cpu_boot)
return ops->cpu_boot(cpu);
@@ -131,6 +297,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
return ret;
}
+#ifdef CONFIG_ARM64_CPU_PARK
+ uninstall_cpu_park(cpu);
+#endif
/*
* CPU was successfully started, wait for it to come online or
* time out.
@@ -844,10 +1013,32 @@ void arch_irq_work_raise(void)
static void local_cpu_stop(void)
{
+#ifdef CONFIG_ARM64_CPU_PARK
+ int cpu;
+ const struct cpu_operations *ops = NULL;
+#endif
+
set_cpu_online(smp_processor_id(), false);
local_daif_mask();
sdei_mask_local_cpu();
+
+#ifdef CONFIG_ARM64_CPU_PARK
+ /*
+ * Go to cpu park state.
+ * Otherwise go to cpu die.
+ */
+ cpu = smp_processor_id();
+ if (kexec_in_progress && park_info.start_v) {
+ machine_kexec_mask_interrupts();
+ cpu_park(cpu);
+
+ ops = get_cpu_ops(cpu);
+ if (ops && ops->cpu_die)
+ ops->cpu_die(cpu);
+ }
+#endif
+
cpu_park_loop();
}
@@ -1053,6 +1244,45 @@ void smp_send_stop(void)
sdei_mask_local_cpu();
}
+#ifdef CONFIG_ARM64_CPU_PARK
+int kexec_smp_send_park(void)
+{
+ unsigned long cpu;
+
+ if (WARN_ON(!kexec_in_progress)) {
+ pr_crit("%s called not in kexec progress.", __func__);
+ return -EPERM;
+ }
+
+ if (mmap_cpu_park_mem() != 0) {
+ pr_info("no cpuparkmem, goto normal way.");
+ return -EPERM;
+ }
+
+ local_irq_disable();
+
+ if (num_online_cpus() > 1) {
+ cpumask_t mask;
+
+ cpumask_copy(&mask, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), &mask);
+
+ for_each_cpu(cpu, &mask)
+ install_cpu_park(cpu);
+ smp_cross_call(&mask, IPI_CPU_STOP);
+
+ /* Wait for other CPUs to park */
+ for_each_cpu(cpu, &mask)
+ cpu_wait_park(cpu);
+ pr_info("smp park other cpus done\n");
+ }
+
+ sdei_mask_local_cpu();
+
+ return 0;
+}
+#endif
+
#ifdef CONFIG_KEXEC_CORE
void crash_smp_send_stop(void)
{
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 794f992..d01259c 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -236,6 +236,57 @@ static void __init fdt_enforce_memory_region(void)
memblock_add(usable_rgns[1].base, usable_rgns[1].size);
}
+#ifdef CONFIG_ARM64_CPU_PARK
+struct cpu_park_info park_info = {
+ .start = 0,
+ .len = PARK_SECTION_SIZE * NR_CPUS,
+ .start_v = 0,
+};
+
+static int __init parse_park_mem(char *p)
+{
+ if (!p)
+ return 0;
+
+ park_info.start = PAGE_ALIGN(memparse(p, NULL));
+ if (park_info.start == 0)
+ pr_info("cpu park mem params[%s]", p);
+
+ return 0;
+}
+early_param("cpuparkmem", parse_park_mem);
+
+static int __init reserve_park_mem(void)
+{
+ if (park_info.start == 0 || park_info.len == 0)
+ return 0;
+
+ park_info.start = PAGE_ALIGN(park_info.start);
+ park_info.len = PAGE_ALIGN(park_info.len);
+
+ if (!memblock_is_region_memory(park_info.start, park_info.len)) {
+ pr_warn("cannot reserve park mem: region is not memory!");
+ goto out;
+ }
+
+ if (memblock_is_region_reserved(park_info.start, park_info.len)) {
+ pr_warn("cannot reserve park mem: region overlaps reserved memory!");
+ goto out;
+ }
+
+ memblock_remove(park_info.start, park_info.len);
+ pr_info("cpu park mem reserved: 0x%016lx - 0x%016lx (%ld MB)",
+ park_info.start, park_info.start + park_info.len,
+ park_info.len >> 20);
+
+ return 0;
+out:
+ park_info.start = 0;
+ park_info.len = 0;
+ return -EINVAL;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -357,6 +408,10 @@ void __init arm64_memblock_init(void)
reserve_crashkernel();
+#ifdef CONFIG_ARM64_CPU_PARK
+ reserve_park_mem();
+#endif
+
reserve_elfcorehdr();
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
--
2.9.5
1
1
MPAM bugfix @ 20210224
James Morse (10):
arm64/mpam: Add mpam driver discovery phase and kbuild boiler plate
cacheinfo: Provide a helper to find a cacheinfo leaf
arm64/mpam: Probe supported partid/pmg ranges from devices
arm64/mpam: Supplement MPAM MSC register layout definitions
arm64/mpam: Probe the features resctrl supports
arm64/mpam: Reset controls when CPUs come online
arm64/mpam: Summarize feature support during mpam_enable()
arm64/mpam: resctrl: Re-synchronise resctrl's view of online CPUs
drivers: base: cacheinfo: Add helper to search cacheinfo by of_node
arm64/mpam: Enabling registering and logging error interrupts
Wang ShaoBo (55):
arm64/mpam: Preparing for MPAM refactoring
arm64/mpam: Add helper for getting mpam sysprops
arm64/mpam: Allocate mpam component configuration arrays
arm64/mpam: Pick MPAM resources and events for resctrl_res exported
arm64/mpam: Init resctrl resources' info from resctrl_res selected
arm64/mpam: resctrl: Handle cpuhp and resctrl_dom allocation
arm64/mpam: Implement helpers for handling configuration and
monitoring
arm64/mpam: Migrate old MSCs' discovery process to new branch
arm64/mpam: Add helper for getting MSCs' configuration
arm64/mpam: Probe partid,pmg and feature capabilities' ranges from
classes
arm64/mpam: resctrl: Rebuild configuration and monitoring pipeline
arm64/mpam: resctrl: Append schemata CDP definitions
arm64/mpam: resctrl: Supplement cdpl2,cdpl3 for mount options
arm64/mpam: resctrl: Add helpers for init and destroy schemata list
arm64/mpam: resctrl: Use resctrl_group_init_alloc() to init schema
list
arm64/mpam: resctrl: Write and read schemata by schema_list
arm64/mpam: Support cdp in mpam_sched_in()
arm64/mpam: resctrl: Update resources reset process
arm64/mpam: resctrl: Update closid alloc and free process with bitmap
arm64/mpam: resctrl: Move ctrlmon sysfile write/read function to
mpam_ctrlmon.c
arm64/mpam: Support cdp on allocating monitors
arm64/mpam: resctrl: Support cdp on monitoring data
arm64/mpam: Clean up header files and rearrange declarations
arm64/mpam: resctrl: Remove ctrlmon sysfile
arm64/mpam: resctrl: Remove unnecessary CONFIG_ARM64
arm64/mpam: Implement intpartid narrowing process
arm64/mpam: Using software-defined id for rdtgroup instead of 32-bit
integer
arm64/mpam: resctrl: collect child mon group's monitor data
arm64/mpam: resctrl: Support cpus' monitoring for mon group
arm64/mpam: resctrl: Support priority and hardlimit(Memory bandwidth)
configuration
arm64/mpam: Store intpri and dspri for mpam device reset
arm64/mpam: Squash default priority from mpam device to class
arm64/mpam: Restore extend ctrls' max width for checking schemata
input
arm64/mpam: Re-plan intpartid narrowing process
arm64/mpam: Add hook-events id for ctrl features
arm64/mpam: Integrate monitor data for Memory Bandwidth if cdp enabled
arm64/mpam: Fix MPAM_ESR intPARTID_range error
arm64/mpam: Separate internal and downstream priority event
arm64/mpam: Remap reqpartid,pmg to rmid and intpartid to closid
arm64/mpam: Add wait queue for monitor alloc and free
arm64/mpam: Add resctrl_ctrl_feature structure to manage ctrl features
arm64/mpam: resctrl: Export resource's properties to info directory
arm64/mpam: Split header files into suitable location
arm64/mpam: resctrl: Add rmid file in resctrl sysfs
arm64/mpam: Filter schema control type with ctrl features
arm64/mpam: Simplify mpamid cdp mapping process
arm64/mpam: Set per-cpu's closid to none zero for cdp
ACPI/MPAM: Use acpi_map_pxm_to_node() to get node id for memory node
arm64/mpam: Supplement additional useful ctrl features for mount
options
arm64/mpam: resctrl: Add proper error handling to resctrl_mount()
arm64/mpam: resctrl: Use resctrl_group_init_alloc() for default group
arm64/mpam: resctrl: Allow setting register MPAMCFG_MBW_MIN to 0
arm64/mpam: resctrl: Refresh cpu mask for handling cpuhp
arm64/mpam: Sort domains when cpu online
arm64/mpam: Fix compile warning
arch/arm64/include/asm/mpam.h | 324 +---
arch/arm64/include/asm/mpam_resource.h | 129 --
arch/arm64/include/asm/mpam_sched.h | 8 -
arch/arm64/include/asm/resctrl.h | 514 +++++-
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/mpam.c | 1499 ----------------
arch/arm64/kernel/mpam/Makefile | 3 +
arch/arm64/kernel/mpam/mpam_ctrlmon.c | 961 ++++++++++
arch/arm64/kernel/mpam/mpam_device.c | 1706 ++++++++++++++++++
arch/arm64/kernel/mpam/mpam_device.h | 140 ++
arch/arm64/kernel/mpam/mpam_internal.h | 345 ++++
arch/arm64/kernel/mpam/mpam_mon.c | 334 ++++
arch/arm64/kernel/mpam/mpam_resctrl.c | 2240 ++++++++++++++++++++++++
arch/arm64/kernel/mpam/mpam_resource.h | 228 +++
arch/arm64/kernel/mpam/mpam_setup.c | 608 +++++++
arch/arm64/kernel/mpam_ctrlmon.c | 623 -------
arch/arm64/kernel/mpam_mon.c | 124 --
drivers/acpi/arm64/mpam.c | 87 +-
drivers/base/cacheinfo.c | 38 +
fs/resctrlfs.c | 396 +++--
include/linux/arm_mpam.h | 118 ++
include/linux/cacheinfo.h | 36 +
include/linux/resctrlfs.h | 30 -
23 files changed, 7521 insertions(+), 2972 deletions(-)
delete mode 100644 arch/arm64/include/asm/mpam_resource.h
delete mode 100644 arch/arm64/kernel/mpam.c
create mode 100644 arch/arm64/kernel/mpam/Makefile
create mode 100644 arch/arm64/kernel/mpam/mpam_ctrlmon.c
create mode 100644 arch/arm64/kernel/mpam/mpam_device.c
create mode 100644 arch/arm64/kernel/mpam/mpam_device.h
create mode 100644 arch/arm64/kernel/mpam/mpam_internal.h
create mode 100644 arch/arm64/kernel/mpam/mpam_mon.c
create mode 100644 arch/arm64/kernel/mpam/mpam_resctrl.c
create mode 100644 arch/arm64/kernel/mpam/mpam_resource.h
create mode 100644 arch/arm64/kernel/mpam/mpam_setup.c
delete mode 100644 arch/arm64/kernel/mpam_ctrlmon.c
delete mode 100644 arch/arm64/kernel/mpam_mon.c
create mode 100644 include/linux/arm_mpam.h
--
2.25.1
1
65

23 Feb '21
From: Li ZhiGang <lizhigang(a)kylinos.cn>
Nationz Tech TCM are used for trusted computing, the chip attached via SPI or LPC.
We have a brief verify/test with this driver on KunPeng920 + openEuler system, with externally compiled module.
Signed-off-by: Li ZhiGang <lizhigang(a)kylinos.cn>
---
drivers/staging/Kconfig | 2 +
drivers/staging/Makefile | 2 +
drivers/staging/gmjstcm/Kconfig | 21 +
drivers/staging/gmjstcm/Makefile | 5 +
drivers/staging/gmjstcm/tcm.c | 949 ++++++++++++++++++++++++++
drivers/staging/gmjstcm/tcm.h | 123 ++++
drivers/staging/gmjstcm/tcm_tis_spi.c | 868 +++++++++++++++++++++++
7 files changed, 1970 insertions(+)
create mode 100644 drivers/staging/gmjstcm/Kconfig
create mode 100644 drivers/staging/gmjstcm/Makefile
create mode 100644 drivers/staging/gmjstcm/tcm.c
create mode 100644 drivers/staging/gmjstcm/tcm.h
create mode 100644 drivers/staging/gmjstcm/tcm_tis_spi.c
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 1abf76be2aa8..d51fa4f4e7ca 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -126,4 +126,6 @@ source "drivers/staging/axis-fifo/Kconfig"
source "drivers/staging/erofs/Kconfig"
+source "drivers/staging/gmjstcm/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index ab0cbe8815b1..6d41915dad5b 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -53,3 +53,5 @@ obj-$(CONFIG_SOC_MT7621) += mt7621-dts/
obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/
obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/
obj-$(CONFIG_EROFS_FS) += erofs/
+obj-$(CONFIG_GMJS_TCM) += gmjstcm/
+
diff --git a/drivers/staging/gmjstcm/Kconfig b/drivers/staging/gmjstcm/Kconfig
new file mode 100644
index 000000000000..5b5397ae1832
--- /dev/null
+++ b/drivers/staging/gmjstcm/Kconfig
@@ -0,0 +1,21 @@
+menu "GMJS TCM support"
+
+config GMJS_TCM
+ bool
+
+config GMJS_TCM_CORE
+ tristate "GMJS TCM core support"
+ depends on ARM64 || MIPS
+ default m
+ select GMJS_TCM
+ help
+ GMJS TCM core support.
+
+config GMJS_TCM_SPI
+ tristate "GMJS TCM support on SPI interface"
+ depends on GMJS_TCM_CORE && SPI_MASTER
+ default m
+ help
+ GMJS TCM support on SPI interface.
+
+endmenu
diff --git a/drivers/staging/gmjstcm/Makefile b/drivers/staging/gmjstcm/Makefile
new file mode 100644
index 000000000000..601c78e44793
--- /dev/null
+++ b/drivers/staging/gmjstcm/Makefile
@@ -0,0 +1,5 @@
+
+obj-$(CONFIG_GMJS_TCM_CORE) += tcm_core.o
+tcm_core-objs := tcm.o
+obj-$(CONFIG_GMJS_TCM_SPI) += tcm_tis_spi.o
+
diff --git a/drivers/staging/gmjstcm/tcm.c b/drivers/staging/gmjstcm/tcm.c
new file mode 100644
index 000000000000..5c41bfa8b423
--- /dev/null
+++ b/drivers/staging/gmjstcm/tcm.c
@@ -0,0 +1,949 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2009 Nationz Technologies Inc.
+ *
+ * Description: Exprot symbol for tcm_tis module
+ *
+ * Major Function: public write read register function etc.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include "tcm.h"
+
+/*
+ * const var
+ */
+enum tcm_const {
+ TCM_MINOR = 224, /* officially assigned */
+ TCM_BUFSIZE = 2048, /* Buffer Size */
+ TCM_NUM_DEVICES = 256, /* Max supporting tcm device number */
+};
+
+/*
+ * CMD duration
+ */
+enum tcm_duration {
+ TCM_SHORT = 0,
+ TCM_MEDIUM = 1,
+ TCM_LONG = 2,
+ TCM_UNDEFINED,
+};
+
+/* Max Total of Command Number */
+#define TCM_MAX_ORDINAL 88 /*243*/
+
+static LIST_HEAD(tcm_chip_list);
+static DEFINE_SPINLOCK(driver_lock); /* spin lock */
+static DECLARE_BITMAP(dev_mask, TCM_NUM_DEVICES);
+
+typedef struct tagTCM_Command {
+ u8 ordinal;
+ u8 DURATION;
+} TCM_Command;
+
+static const TCM_Command TCM_Command_List[TCM_MAX_ORDINAL + 1] = {
+ {/*TCM_ORD_ActivateIdentity, */122, 1},
+ {/*TCM_ORD_CertifyKey, */50, 1},
+ {/*TCM_ORD_CertifyKeyM, */51, 1},
+ {/*TCM_ORD_ChangeAuth, */12, 1},
+ {/*TCM_ORD_ChangeAuthOwner, */16, 0},
+ {/*TCM_ORD_ContinueSelfTeSt, */83, 2},
+ {/*TCM_ORD_CreateCounter, */220, 0},
+ {/*TCM_ORD_CreateWrapKey, */31, 2},
+ {/*TCM_ORD_DiSableForceClear, */94, 0},
+ {/*TCM_ORD_DiSableOwnerClear, */92, 0},
+ {/*TCM_ORD_EStabliShTranSport, */230, 0},
+ {/*TCM_ORD_ExecuteTranSport, */231, 2},
+ {/*TCM_ORD_Extend, */20, 0},
+ {/*TCM_ORD_FieldUpgrade, */170, 2},
+ {/*TCM_ORD_FluShSpecific, */186, 0},
+ {/*TCM_ORD_ForceClear, */93, 0},
+ {/*TCM_ORD_GetAuditDigeSt, */133, 0},
+ {/*TCM_ORD_GetAuditDigeStSigned, */134, 1},
+ {/*TCM_ORD_GetCapability, */101, 0},
+ {/*TCM_ORD_GetPubKey, */33, 0},
+ {/*TCM_ORD_GetRandoM, */70, 0},
+ {/*TCM_ORD_GetTeStReSult, */84, 0},
+ {/*TCM_ORD_GetTickS, */241, 0},
+ {/*TCM_ORD_IncreMentCounter, */221, 0},
+ {/*TCM_ORD_LoadContext, */185, 1},
+ {/*TCM_ORD_MakeIdentity, */121, 2},
+ {/*TCM_ORD_NV_DefineSpace, */204, 0},
+ {/*TCM_ORD_NV_ReadValue, */207, 0},
+ {/*TCM_ORD_NV_ReadValueAuth, */208, 0},
+ {/*TCM_ORD_NV_WriteValue, */205, 0},
+ {/*TCM_ORD_NV_WriteValueAuth, */206, 0},
+ {/*TCM_ORD_OwnerClear, */91, 0},
+ {/*TCM_ORD_OwnerReadInternalPub, */129, 0},
+ {/*TCM_ORD_OwnerSetDiSable, */110, 0},
+ {/*TCM_ORD_PCR_ReSet, */200, 0},
+ {/*TCM_ORD_PcrRead, */21, 0},
+ {/*TCM_ORD_PhySicalDiSable, */112, 0},
+ {/*TCM_ORD_PhySicalEnable, */111, 0},
+ {/*TCM_ORD_PhySicalSetDeactivated, */114, 0},
+ {/*TCM_ORD_Quote, */22, 1},
+ {/*TCM_ORD_QuoteM, */62, 1},
+ {/*TCM_ORD_ReadCounter, */222, 0},
+ {/*TCM_ORD_ReadPubek, */124, 0},
+ {/*TCM_ORD_ReleaSeCounter, */223, 0},
+ {/*TCM_ORD_ReleaSeCounterOwner, */224, 0},
+ {/*TCM_ORD_ReleaSeTranSportSigned, */232, 1},
+ {/*TCM_ORD_ReSetLockValue, */64, 0},
+ {/*TCM_ORD_RevokeTruSt, */128, 0},
+ {/*TCM_ORD_SaveContext, */184, 1},
+ {/*TCM_ORD_SaveState, */152, 1},
+ {/*TCM_ORD_Seal, */23, 1},
+ {/*TCM_ORD_Sealx, */61, 1},
+ {/*TCM_ORD_SelfTeStFull, */80, 2},
+ {/*TCM_ORD_SetCapability, */63, 0},
+ {/*TCM_ORD_SetOperatorAuth, */116, 0},
+ {/*TCM_ORD_SetOrdinalAuditStatuS, */141, 0},
+ {/*TCM_ORD_SetOwnerInStall, */113, 0},
+ {/*TCM_ORD_SetTeMpDeactivated, */115, 0},
+ {/*TCM_ORD_Sign, */60, 1},
+ {/*TCM_ORD_Startup, */153, 0},
+ {/*TCM_ORD_TakeOwnerShip, */13, 1},
+ {/*TCM_ORD_TickStaMpBlob, */242, 1},
+ {/*TCM_ORD_UnSeal, */24, 1},
+ {/*TSC_ORD_PhySicalPreSence, */10, 0},
+ {/*TSC_ORD_ReSetEStabliShMentBit, */11, 0},
+ {/*TCM_ORD_WrapKey, */189, 2},
+ {/*TCM_ORD_APcreate, */191, 0},
+ {/*TCM_ORD_APTerMinate, */192, 0},
+ {/*TCM_ORD_CreateMigratedBlob, */193, 1},
+ {/*TCM_ORD_ConvertMigratedBlob, */194, 1},
+ {/*TCM_ORD_AuthorizeMigrationKey, */195, 0},
+ {/*TCM_ORD_SMS4Encrypt, */197, 1},
+ {/*TCM_ORD_SMS4Decrypt, */198, 1},
+ {/*TCM_ORD_ReadEKCert, */199, 1},
+ {/*TCM_ORD_WriteEKCert, */233, 1},
+ {/*TCM_ORD_SCHStart, */234, 0},
+ {/*TCM_ORD_SCHUpdata, */235, 0},
+ {/*TCM_ORD_SCHCoMplete, */236, 0},
+ {/*TCM_ORD_SCHCoMpleteExtend, */237, 0},
+ {/*TCM_ORD_ECCDecrypt, */238, 1},
+ {/*TCM_ORD_LoadKey, */239, 1},
+ {/*TCM_ORD_CreateEndorSeMentKeyPair, */120, 2},
+ {/*TCM_ORD_CreateRevocableEK, */127, 2},
+ {/*TCM_ORD_ReleaSeECCExchangeSeSSion, */174, 1},
+ {/*TCM_ORD_CreateECCExchangeSeSSion, */175, 1},
+ {/*TCM_ORD_GetKeyECCExchangeSeSSion, */176, 1},
+ {/*TCM_ORD_ActivatePEK, */217, 1},
+ {/*TCM_ORD_ActivatePEKCert, */218, 1},
+ {0, 0}
+};
+
+static void user_reader_timeout(struct timer_list *t)
+{
+ struct tcm_chip *chip = from_timer(chip, t, user_read_timer);
+
+ schedule_work(&chip->work);
+}
+
+static void timeout_work(struct work_struct *work)
+{
+ struct tcm_chip *chip = container_of(work, struct tcm_chip, work);
+
+ mutex_lock(&chip->buffer_mutex);
+ atomic_set(&chip->data_pending, 0);
+ memset(chip->data_buffer, 0, TCM_BUFSIZE);
+ mutex_unlock(&chip->buffer_mutex);
+}
+
+unsigned long tcm_calc_ordinal_duration(struct tcm_chip *chip,
+ u32 ordinal)
+{
+ int duration_idx = TCM_UNDEFINED;
+ int duration = 0;
+ int i = 0;
+
+ for (i = 0; i < TCM_MAX_ORDINAL; i++) {
+ if (ordinal == TCM_Command_List[i].ordinal) {
+ duration_idx = TCM_Command_List[i].DURATION;
+ break;
+ }
+ }
+
+ if (duration_idx != TCM_UNDEFINED)
+ duration = chip->vendor.duration[duration_idx];
+ if (duration <= 0)
+ return 2 * 60 * HZ;
+ else
+ return duration;
+}
+EXPORT_SYMBOL_GPL(tcm_calc_ordinal_duration);
+
+/*
+ * Internal kernel interface to transmit TCM commands
+ * buff format: TAG(2 bytes) + Total Size(4 bytes ) +
+ * Command Ordinal(4 bytes ) + ......
+ */
+static ssize_t tcm_transmit(struct tcm_chip *chip, const char *buf,
+ size_t bufsiz)
+{
+ ssize_t rc = 0;
+ u32 count = 0, ordinal = 0;
+ unsigned long stop = 0;
+
+ count = be32_to_cpu(*((__be32 *)(buf + 2))); /* buff size */
+ ordinal = be32_to_cpu(*((__be32 *)(buf + 6))); /* command ordinal */
+
+ if (count == 0)
+ return -ENODATA;
+ if (count > bufsiz) { /* buff size err ,invalid buff stream */
+ dev_err(chip->dev, "invalid count value %x, %zx\n",
+ count, bufsiz);
+ return -E2BIG;
+ }
+
+ mutex_lock(&chip->tcm_mutex); /* enter mutex */
+
+ rc = chip->vendor.send(chip, (u8 *)buf, count);
+ if (rc < 0) {
+ dev_err(chip->dev, "%s: tcm_send: error %zd\n",
+ __func__, rc);
+ goto out;
+ }
+
+ if (chip->vendor.irq)
+ goto out_recv;
+
+ stop = jiffies + tcm_calc_ordinal_duration(chip,
+ ordinal); /* cmd duration */
+ do {
+ u8 status = chip->vendor.status(chip);
+
+ if ((status & chip->vendor.req_complete_mask) ==
+ chip->vendor.req_complete_val)
+ goto out_recv;
+
+ if ((status == chip->vendor.req_canceled)) {
+ dev_err(chip->dev, "Operation Canceled\n");
+ rc = -ECANCELED;
+ goto out;
+ }
+
+ msleep(TCM_TIMEOUT); /* CHECK */
+ rmb();
+ } while (time_before(jiffies, stop));
+ /* time out */
+ chip->vendor.cancel(chip);
+ dev_err(chip->dev, "Operation Timed out\n");
+ rc = -ETIME;
+ goto out;
+
+out_recv:
+ rc = chip->vendor.recv(chip, (u8 *)buf, bufsiz);
+ if (rc < 0)
+ dev_err(chip->dev, "%s: tcm_recv: error %zd\n",
+ __func__, rc);
+out:
+ mutex_unlock(&chip->tcm_mutex);
+ return rc;
+}
+
+#define TCM_DIGEST_SIZE 32
+#define TCM_ERROR_SIZE 10
+#define TCM_RET_CODE_IDX 6
+#define TCM_GET_CAP_RET_SIZE_IDX 10
+#define TCM_GET_CAP_RET_UINT32_1_IDX 14
+#define TCM_GET_CAP_RET_UINT32_2_IDX 18
+#define TCM_GET_CAP_RET_UINT32_3_IDX 22
+#define TCM_GET_CAP_RET_UINT32_4_IDX 26
+#define TCM_GET_CAP_PERM_DISABLE_IDX 16
+#define TCM_GET_CAP_PERM_INACTIVE_IDX 18
+#define TCM_GET_CAP_RET_BOOL_1_IDX 14
+#define TCM_GET_CAP_TEMP_INACTIVE_IDX 16
+
+#define TCM_CAP_IDX 13
+#define TCM_CAP_SUBCAP_IDX 21
+
+enum tcm_capabilities {
+ TCM_CAP_FLAG = 4,
+ TCM_CAP_PROP = 5,
+};
+
+enum tcm_sub_capabilities {
+ TCM_CAP_PROP_PCR = 0x1, /* tcm 0x101 */
+ TCM_CAP_PROP_MANUFACTURER = 0x3, /* tcm 0x103 */
+ TCM_CAP_FLAG_PERM = 0x8, /* tcm 0x108 */
+ TCM_CAP_FLAG_VOL = 0x9, /* tcm 0x109 */
+ TCM_CAP_PROP_OWNER = 0x11, /* tcm 0x101 */
+ TCM_CAP_PROP_TIS_TIMEOUT = 0x15, /* tcm 0x115 */
+ TCM_CAP_PROP_TIS_DURATION = 0x20, /* tcm 0x120 */
+};
+
+/*
+ * This is a semi generic GetCapability command for use
+ * with the capability type TCM_CAP_PROP or TCM_CAP_FLAG
+ * and their associated sub_capabilities.
+ */
+
+static const u8 tcm_cap[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND 0xc1*/
+ 0, 0, 0, 22, /* length */
+ 0, 0, 128, 101, /* TCM_ORD_GetCapability */
+ 0, 0, 0, 0, /* TCM_CAP_<TYPE> */
+ 0, 0, 0, 4, /* TCM_CAP_SUB_<TYPE> size */
+ 0, 0, 1, 0 /* TCM_CAP_SUB_<TYPE> */
+};
+
+static ssize_t transmit_cmd(struct tcm_chip *chip, u8 *data, int len,
+ char *desc)
+{
+ int err = 0;
+
+ len = tcm_transmit(chip, data, len);
+ if (len < 0)
+ return len;
+ if (len == TCM_ERROR_SIZE) {
+ err = be32_to_cpu(*((__be32 *)(data + TCM_RET_CODE_IDX)));
+ dev_dbg(chip->dev, "A TCM error (%d) occurred %s\n", err, desc);
+ return err;
+ }
+ return 0;
+}
+
+/*
+ * Get default timeouts value form tcm by GetCapability with TCM_CAP_PROP_TIS_TIMEOUT prop
+ */
+void tcm_get_timeouts(struct tcm_chip *chip)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tcm_cap), 30)];
+ ssize_t rc = 0;
+ u32 timeout = 0;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_PROP;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_PROP_TIS_TIMEOUT;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the timeouts");
+ if (rc)
+ goto duration;
+
+ if (be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_SIZE_IDX))) !=
+ 4 * sizeof(u32))
+ goto duration;
+
+ /* Don't overwrite default if value is 0 */
+ timeout = be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_UINT32_1_IDX)));
+ if (timeout)
+ chip->vendor.timeout_a = msecs_to_jiffies(timeout);
+ timeout = be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_UINT32_2_IDX)));
+ if (timeout)
+ chip->vendor.timeout_b = msecs_to_jiffies(timeout);
+ timeout = be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_UINT32_3_IDX)));
+ if (timeout)
+ chip->vendor.timeout_c = msecs_to_jiffies(timeout);
+ timeout = be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_UINT32_4_IDX)));
+ if (timeout)
+ chip->vendor.timeout_d = msecs_to_jiffies(timeout);
+
+duration:
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_PROP;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_PROP_TIS_DURATION;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the durations");
+ if (rc)
+ return;
+
+ if (be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_SIZE_IDX))) !=
+ 3 * sizeof(u32))
+ return;
+
+ chip->vendor.duration[TCM_SHORT] =
+ msecs_to_jiffies(be32_to_cpu(*((__be32 *)(data +
+ TCM_GET_CAP_RET_UINT32_1_IDX))));
+ chip->vendor.duration[TCM_MEDIUM] =
+ msecs_to_jiffies(be32_to_cpu(*((__be32 *)(data +
+ TCM_GET_CAP_RET_UINT32_2_IDX))));
+ chip->vendor.duration[TCM_LONG] =
+ msecs_to_jiffies(be32_to_cpu(*((__be32 *)(data +
+ TCM_GET_CAP_RET_UINT32_3_IDX))));
+}
+EXPORT_SYMBOL_GPL(tcm_get_timeouts);
+
+ssize_t tcm_show_enabled(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tcm_cap), 35)];
+ ssize_t rc = 0;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_FLAG;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ if (data[TCM_GET_CAP_PERM_DISABLE_IDX])
+ return sprintf(buf, "disable\n");
+ else
+ return sprintf(buf, "enable\n");
+}
+EXPORT_SYMBOL_GPL(tcm_show_enabled);
+
+ssize_t tcm_show_active(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tcm_cap), 35)];
+ ssize_t rc = 0;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_FLAG;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ if (data[TCM_GET_CAP_PERM_INACTIVE_IDX])
+ return sprintf(buf, "deactivated\n");
+ else
+ return sprintf(buf, "activated\n");
+}
+EXPORT_SYMBOL_GPL(tcm_show_active);
+
+ssize_t tcm_show_owned(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[sizeof(tcm_cap)];
+ ssize_t rc = 0;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_PROP;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_PROP_OWNER;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the owner state");
+ if (rc)
+ return 0;
+ if (data[TCM_GET_CAP_RET_BOOL_1_IDX])
+ return sprintf(buf, "Owner installed\n");
+ else
+ return sprintf(buf, "Owner have not installed\n");
+}
+EXPORT_SYMBOL_GPL(tcm_show_owned);
+
+ssize_t tcm_show_temp_deactivated(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 data[sizeof(tcm_cap)];
+ ssize_t rc = 0;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_FLAG;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_FLAG_VOL;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the temporary state");
+ if (rc)
+ return 0;
+ if (data[TCM_GET_CAP_TEMP_INACTIVE_IDX])
+ return sprintf(buf, "Temp deactivated\n");
+ else
+ return sprintf(buf, "activated\n");
+}
+EXPORT_SYMBOL_GPL(tcm_show_temp_deactivated);
+
+static const u8 pcrread[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 14, /* length */
+ 0, 0, 128, 21, /* TCM_ORD_PcrRead */
+ 0, 0, 0, 0 /* PCR index */
+};
+
+ssize_t tcm_show_pcrs(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[1024];
+ ssize_t rc = 0;
+ int i = 0, j = 0, num_pcrs = 0;
+ __be32 index = 0;
+ char *str = buf;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_PROP;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_PROP_PCR;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the number of PCRS");
+ if (rc)
+ return 0;
+
+ num_pcrs = be32_to_cpu(*((__be32 *)(data + 14)));
+ for (i = 0; i < num_pcrs; i++) {
+ memcpy(data, pcrread, sizeof(pcrread));
+ index = cpu_to_be32(i);
+ memcpy(data + 10, &index, 4);
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to read a PCR");
+ if (rc)
+ goto out;
+ str += sprintf(str, "PCR-%02d: ", i);
+ for (j = 0; j < TCM_DIGEST_SIZE; j++)
+ str += sprintf(str, "%02X ", *(data + 10 + j));
+ str += sprintf(str, "\n");
+ memset(data, 0, 1024);
+ }
+out:
+ return str - buf;
+}
+EXPORT_SYMBOL_GPL(tcm_show_pcrs);
+
+#define READ_PUBEK_RESULT_SIZE 128
+static const u8 readpubek[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 42, /* length */
+ 0, 0, 128, 124, /* TCM_ORD_ReadPubek */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* NONCE */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+ssize_t tcm_show_pubek(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[READ_PUBEK_RESULT_SIZE] = {0};
+ ssize_t err = 0;
+ int i = 0, rc = 0;
+ char *str = buf;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, readpubek, sizeof(readpubek));
+
+ err = transmit_cmd(chip, data, sizeof(data),
+ "attempting to read the PUBEK");
+ if (err)
+ goto out;
+
+ str += sprintf(str, "PUBEK:");
+ for (i = 0 ; i < 65 ; i++) {
+ if ((i) % 16 == 0)
+ str += sprintf(str, "\n");
+ str += sprintf(str, "%02X ", data[i+10]);
+ }
+
+ str += sprintf(str, "\n");
+out:
+ rc = str - buf;
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tcm_show_pubek);
+
+#define CAP_VERSION_1_1 6
+#define CAP_VERSION_1_2 0x1A
+#define CAP_VERSION_IDX 13
+static const u8 cap_version[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 18, /* length */
+ 0, 0, 128, 101, /* TCM_ORD_GetCapability */
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+
+ssize_t tcm_show_caps(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 data[max_t(int, max(ARRAY_SIZE(tcm_cap), ARRAY_SIZE(cap_version)), 30)];
+ ssize_t rc = 0;
+ char *str = buf;
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tcm_cap, sizeof(tcm_cap));
+ data[TCM_CAP_IDX] = TCM_CAP_PROP;
+ data[TCM_CAP_SUBCAP_IDX] = TCM_CAP_PROP_MANUFACTURER;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the manufacturer");
+ if (rc)
+ return 0;
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*((__be32 *)(data + TCM_GET_CAP_RET_UINT32_1_IDX))));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+ data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the 1.1 version");
+ if (rc)
+ goto out;
+
+ str += sprintf(str, "Firmware version: %02X.%02X.%02X.%02X\n",
+ (int)data[14], (int)data[15], (int)data[16],
+ (int)data[17]);
+
+out:
+ return str - buf;
+}
+EXPORT_SYMBOL_GPL(tcm_show_caps);
+
+ssize_t tcm_store_cancel(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return 0;
+
+ chip->vendor.cancel(chip);
+ return count;
+}
+EXPORT_SYMBOL_GPL(tcm_store_cancel);
+
+/*
+ * Device file system interface to the TCM
+ * when App call file open in usr space ,this func will respone
+ */
+int tcm_open(struct inode *inode, struct file *file)
+{
+ int rc = 0, minor = iminor(inode);
+ struct tcm_chip *chip = NULL, *pos = NULL;
+
+ spin_lock(&driver_lock);
+
+ list_for_each_entry(pos, &tcm_chip_list, list) {
+ if (pos->vendor.miscdev.minor == minor) {
+ chip = pos;
+ break;
+ }
+ }
+
+ if (chip == NULL) {
+ rc = -ENODEV;
+ goto err_out;
+ }
+
+ if (chip->num_opens) {
+ dev_dbg(chip->dev, "Another process owns this TCM\n");
+ rc = -EBUSY;
+ goto err_out;
+ }
+
+ chip->num_opens++;
+ get_device(chip->dev);
+
+ spin_unlock(&driver_lock);
+
+ chip->data_buffer = kmalloc(TCM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+ if (chip->data_buffer == NULL) {
+ chip->num_opens--;
+ put_device(chip->dev);
+ return -ENOMEM;
+ }
+
+ atomic_set(&chip->data_pending, 0);
+
+ file->private_data = chip;
+ return 0;
+
+err_out:
+ spin_unlock(&driver_lock);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tcm_open);
+
+int tcm_release(struct inode *inode, struct file *file)
+{
+ struct tcm_chip *chip = file->private_data;
+
+ spin_lock(&driver_lock);
+ file->private_data = NULL;
+ chip->num_opens--;
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ flush_work(&chip->work);
+ atomic_set(&chip->data_pending, 0);
+ put_device(chip->dev);
+ kfree(chip->data_buffer);
+ spin_unlock(&driver_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tcm_release);
+
+ssize_t tcm_write(struct file *file, const char __user *buf,
+ size_t size, loff_t *off)
+{
+ struct tcm_chip *chip = file->private_data;
+ int in_size = size, out_size;
+
+ /*
+ * cannot perform a write until the read has cleared
+ * either via tcm_read or a user_read_timer timeout
+ */
+ while (atomic_read(&chip->data_pending) != 0)
+ msleep(TCM_TIMEOUT);
+
+ mutex_lock(&chip->buffer_mutex);
+
+ if (in_size > TCM_BUFSIZE)
+ in_size = TCM_BUFSIZE;
+
+ if (copy_from_user(chip->data_buffer, (void __user *)buf, in_size)) {
+ mutex_unlock(&chip->buffer_mutex);
+ return -EFAULT;
+ }
+
+ /* atomic tcm command send and result receive */
+ out_size = tcm_transmit(chip, chip->data_buffer, TCM_BUFSIZE);
+
+ if (out_size >= 0) {
+ atomic_set(&chip->data_pending, out_size);
+ mutex_unlock(&chip->buffer_mutex);
+
+ /* Set a timeout by which the reader must come claim the result */
+ mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
+ } else
+ mutex_unlock(&chip->buffer_mutex);
+
+ return in_size;
+}
+EXPORT_SYMBOL_GPL(tcm_write);
+
+ssize_t tcm_read(struct file *file, char __user *buf,
+ size_t size, loff_t *off)
+{
+ struct tcm_chip *chip = file->private_data;
+ int ret_size = 0;
+
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ flush_work(&chip->work);
+ ret_size = atomic_read(&chip->data_pending);
+ atomic_set(&chip->data_pending, 0);
+ if (ret_size > 0) { /* relay data */
+ if (size < ret_size)
+ ret_size = size;
+
+ mutex_lock(&chip->buffer_mutex);
+ if (copy_to_user(buf, chip->data_buffer, ret_size))
+ ret_size = -EFAULT;
+ mutex_unlock(&chip->buffer_mutex);
+ }
+
+ return ret_size;
+}
+EXPORT_SYMBOL_GPL(tcm_read);
+
+void tcm_remove_hardware(struct device *dev)
+{
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL) {
+ dev_err(dev, "No device data found\n");
+ return;
+ }
+
+ spin_lock(&driver_lock);
+ list_del(&chip->list);
+ spin_unlock(&driver_lock);
+
+ dev_set_drvdata(dev, NULL);
+ misc_deregister(&chip->vendor.miscdev);
+ kfree(chip->vendor.miscdev.name);
+
+ sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
+ /* tcm_bios_log_teardown(chip->bios_dir); */
+
+ clear_bit(chip->dev_num, dev_mask);
+ kfree(chip);
+ put_device(dev);
+}
+EXPORT_SYMBOL_GPL(tcm_remove_hardware);
+
+static u8 savestate[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* blob length (in bytes) */
+ 0, 0, 128, 152 /* TCM_ORD_SaveState */
+};
+
+/*
+ * We are about to suspend. Save the TCM state
+ * so that it can be restored.
+ */
+int tcm_pm_suspend(struct device *dev, pm_message_t pm_state)
+{
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ tcm_transmit(chip, savestate, sizeof(savestate));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tcm_pm_suspend);
+
+int tcm_pm_suspend_p(struct device *dev)
+{
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ tcm_transmit(chip, savestate, sizeof(savestate));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tcm_pm_suspend_p);
+
+void tcm_startup(struct tcm_chip *chip)
+{
+ u8 start_up[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 12, /* blob length (in bytes) */
+ 0, 0, 128, 153, /* TCM_ORD_SaveState */
+ 0, 1
+ };
+ if (chip == NULL)
+ return;
+ tcm_transmit(chip, start_up, sizeof(start_up));
+}
+EXPORT_SYMBOL_GPL(tcm_startup);
+
+/*
+ * Resume from a power safe. The BIOS already restored
+ * the TCM state.
+ */
+int tcm_pm_resume(struct device *dev)
+{
+ u8 start_up[] = {
+ 0, 193, /* TCM_TAG_RQU_COMMAND */
+ 0, 0, 0, 12, /* blob length (in bytes) */
+ 0, 0, 128, 153, /* TCM_ORD_SaveState */
+ 0, 1
+ };
+ struct tcm_chip *chip = dev_get_drvdata(dev);
+ /* dev_info(chip->dev ,"--call tcm_pm_resume\n"); */
+ if (chip == NULL)
+ return -ENODEV;
+
+ tcm_transmit(chip, start_up, sizeof(start_up));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tcm_pm_resume);
+
+/*
+ * Called from tcm_<specific>.c probe function only for devices
+ * the driver has determined it should claim. Prior to calling
+ * this function the specific probe function has called pci_enable_device
+ * upon errant exit from this function specific probe function should call
+ * pci_disable_device
+ */
+struct tcm_chip *tcm_register_hardware(struct device *dev,
+ const struct tcm_vendor_specific *entry)
+{
+ int rc;
+#define DEVNAME_SIZE 7
+
+ char *devname = NULL;
+ struct tcm_chip *chip = NULL;
+
+ /* Driver specific per-device data */
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ dev_err(dev, "chip kzalloc err\n");
+ return NULL;
+ }
+
+ mutex_init(&chip->buffer_mutex);
+ mutex_init(&chip->tcm_mutex);
+ INIT_LIST_HEAD(&chip->list);
+
+ INIT_WORK(&chip->work, timeout_work);
+ timer_setup(&chip->user_read_timer, user_reader_timeout, 0);
+
+ memcpy(&chip->vendor, entry, sizeof(struct tcm_vendor_specific));
+
+ chip->dev_num = find_first_zero_bit(dev_mask, TCM_NUM_DEVICES);
+
+ if (chip->dev_num >= TCM_NUM_DEVICES) {
+ dev_err(dev, "No available tcm device numbers\n");
+ kfree(chip);
+ return NULL;
+ } else if (chip->dev_num == 0)
+ chip->vendor.miscdev.minor = TCM_MINOR;
+ else
+ chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
+
+ set_bit(chip->dev_num, dev_mask);
+
+ devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
+ scnprintf(devname, DEVNAME_SIZE, "%s%d", "tcm", chip->dev_num);
+ chip->vendor.miscdev.name = devname;
+
+ /* chip->vendor.miscdev.dev = dev; */
+
+ chip->dev = get_device(dev);
+
+ if (misc_register(&chip->vendor.miscdev)) {
+ dev_err(chip->dev,
+ "unable to misc_register %s, minor %d\n",
+ chip->vendor.miscdev.name,
+ chip->vendor.miscdev.minor);
+ put_device(dev);
+ clear_bit(chip->dev_num, dev_mask);
+ kfree(chip);
+ kfree(devname);
+ return NULL;
+ }
+
+ spin_lock(&driver_lock);
+ dev_set_drvdata(dev, chip);
+ list_add(&chip->list, &tcm_chip_list);
+ spin_unlock(&driver_lock);
+
+ rc = sysfs_create_group(&dev->kobj, chip->vendor.attr_group);
+ /* chip->bios_dir = tcm_bios_log_setup(devname); */
+
+ return chip;
+}
+EXPORT_SYMBOL_GPL(tcm_register_hardware);
+
+static int __init tcm_init_module(void)
+{
+ return 0;
+}
+
+static void __exit tcm_exit_module(void)
+{
+}
+
+module_init(tcm_init_module);
+module_exit(tcm_exit_module);
+
+MODULE_AUTHOR("Nationz Technologies Inc.");
+MODULE_DESCRIPTION("TCM Driver");
+MODULE_VERSION("1.1.1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gmjstcm/tcm.h b/drivers/staging/gmjstcm/tcm.h
new file mode 100644
index 000000000000..b8cafe78d590
--- /dev/null
+++ b/drivers/staging/gmjstcm/tcm.h
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2009 Nationz Technologies Inc.
+ *
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+struct device;
+struct tcm_chip;
+
+enum tcm_timeout {
+ TCM_TIMEOUT = 5,
+};
+
+/* TCM addresses */
+enum tcm_addr {
+ TCM_SUPERIO_ADDR = 0x2E,
+ TCM_ADDR = 0x4E,
+};
+
+extern ssize_t tcm_show_pubek(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_show_pcrs(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_show_caps(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_store_cancel(struct device *, struct device_attribute *attr,
+ const char *, size_t);
+extern ssize_t tcm_show_enabled(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_show_active(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_show_owned(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tcm_show_temp_deactivated(struct device *,
+ struct device_attribute *attr, char *);
+
+struct tcm_vendor_specific {
+ const u8 req_complete_mask;
+ const u8 req_complete_val;
+ const u8 req_canceled;
+ void __iomem *iobase; /* ioremapped address */
+ void __iomem *iolbc;
+ unsigned long base; /* TCM base address */
+
+ int irq;
+
+ int region_size;
+ int have_region;
+
+ int (*recv)(struct tcm_chip *, u8 *, size_t);
+ int (*send)(struct tcm_chip *, u8 *, size_t);
+ void (*cancel)(struct tcm_chip *);
+ u8 (*status)(struct tcm_chip *);
+ struct miscdevice miscdev;
+ struct attribute_group *attr_group;
+ struct list_head list;
+ int locality;
+ unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
+ unsigned long duration[3]; /* jiffies */
+
+ wait_queue_head_t read_queue;
+ wait_queue_head_t int_queue;
+};
+
+struct tcm_chip {
+ struct device *dev; /* Device stuff */
+
+ int dev_num; /* /dev/tcm# */
+ int num_opens; /* only one allowed */
+ int time_expired;
+
+ /* Data passed to and from the tcm via the read/write calls */
+ u8 *data_buffer;
+ atomic_t data_pending;
+ struct mutex buffer_mutex;
+
+ struct timer_list user_read_timer; /* user needs to claim result */
+ struct work_struct work;
+ struct mutex tcm_mutex; /* tcm is processing */
+
+ struct tcm_vendor_specific vendor;
+
+ struct dentry **bios_dir;
+
+ struct list_head list;
+};
+
+#define to_tcm_chip(n) container_of(n, struct tcm_chip, vendor)
+
+static inline int tcm_read_index(int base, int index)
+{
+ outb(index, base);
+ return inb(base+1) & 0xFF;
+}
+
+static inline void tcm_write_index(int base, int index, int value)
+{
+ outb(index, base);
+ outb(value & 0xFF, base+1);
+}
+extern void tcm_startup(struct tcm_chip *);
+extern void tcm_get_timeouts(struct tcm_chip *);
+extern unsigned long tcm_calc_ordinal_duration(struct tcm_chip *, u32);
+extern struct tcm_chip *tcm_register_hardware(struct device *,
+ const struct tcm_vendor_specific *);
+extern int tcm_open(struct inode *, struct file *);
+extern int tcm_release(struct inode *, struct file *);
+extern ssize_t tcm_write(struct file *, const char __user *, size_t,
+ loff_t *);
+extern ssize_t tcm_read(struct file *, char __user *, size_t, loff_t *);
+extern void tcm_remove_hardware(struct device *);
+extern int tcm_pm_suspend(struct device *, pm_message_t);
+extern int tcm_pm_suspend_p(struct device *);
+extern int tcm_pm_resume(struct device *);
+
diff --git a/drivers/staging/gmjstcm/tcm_tis_spi.c b/drivers/staging/gmjstcm/tcm_tis_spi.c
new file mode 100644
index 000000000000..db30a5b4c47d
--- /dev/null
+++ b/drivers/staging/gmjstcm/tcm_tis_spi.c
@@ -0,0 +1,868 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Kylin Tech. Co., Ltd.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/acpi.h>
+#include <linux/spi/spi.h>
+
+#include "tcm.h"
+
+#if !defined(CONFIG_KYLINOS_SERVER) && !defined(CONFIG_KYLINOS_DESKTOP)
+static int is_ft_all(void) {
+ return 0;
+}
+#endif
+
+#define TCM_HEADER_SIZE 10
+
+static bool tcm_debug;
+module_param_named(debug, tcm_debug, bool, 0600);
+MODULE_PARM_DESC(debug, "Turn TCM debugging mode on and off");
+
+#define tcm_dbg(fmt, args...) \
+{ \
+ if (tcm_debug) \
+ pr_err(fmt, ## args); \
+}
+
+enum tis_access {
+ TCM_ACCESS_VALID = 0x80,
+ TCM_ACCESS_ACTIVE_LOCALITY = 0x20,
+ TCM_ACCESS_REQUEST_PENDING = 0x04,
+ TCM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum tis_status {
+ TCM_STS_VALID = 0x80,
+ TCM_STS_COMMAND_READY = 0x40,
+ TCM_STS_GO = 0x20,
+ TCM_STS_DATA_AVAIL = 0x10,
+ TCM_STS_DATA_EXPECT = 0x08,
+};
+
+enum tis_int_flags {
+ TCM_GLOBAL_INT_ENABLE = 0x80000000,
+ TCM_INTF_BURST_COUNT_STATIC = 0x100,
+ TCM_INTF_CMD_READY_INT = 0x080,
+ TCM_INTF_INT_EDGE_FALLING = 0x040,
+ TCM_INTF_INT_EDGE_RISING = 0x020,
+ TCM_INTF_INT_LEVEL_LOW = 0x010,
+ TCM_INTF_INT_LEVEL_HIGH = 0x008,
+ TCM_INTF_LOCALITY_CHANGE_INT = 0x004,
+ TCM_INTF_STS_VALID_INT = 0x002,
+ TCM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+ TIS_SHORT_TIMEOUT = 750, /* ms */
+ TIS_LONG_TIMEOUT = 2000, /* 2 sec */
+};
+
+#define TCM_ACCESS(l) (0x0000 | ((l) << 12))
+#define TCM_INT_ENABLE(l) (0x0008 | ((l) << 12)) /* interperet */
+#define TCM_INT_VECTOR(l) (0x000C | ((l) << 12))
+#define TCM_INT_STATUS(l) (0x0010 | ((l) << 12))
+#define TCM_INTF_CAPS(l) (0x0014 | ((l) << 12))
+#define TCM_STS(l) (0x0018 | ((l) << 12))
+#define TCM_DATA_FIFO(l) (0x0024 | ((l) << 12))
+
+#define TCM_DID_VID(l) (0x0F00 | ((l) << 12))
+#define TCM_RID(l) (0x0F04 | ((l) << 12))
+
+#define TIS_MEM_BASE_huawei 0x3fed40000LL
+
+#define MAX_SPI_FRAMESIZE 64
+
+//
+#define _CPU_FT2000A4
+#define REUSE_CONF_REG_BASE 0x28180208
+#define REUSE_GPIO1_A5_BASE 0x28005000
+
+static void *__iomem reuse_conf_reg;
+static void *__iomem gpio1_a5;
+
+//
+static LIST_HEAD(tis_chips);
+static DEFINE_SPINLOCK(tis_lock);
+
+struct chip_data {
+ u8 cs;
+ u8 tmode;
+ u8 type;
+ u8 poll_mode;
+ u16 clk_div;
+ u32 speed_hz;
+ void (*cs_control)(u32 command);
+};
+
+struct tcm_tis_spi_phy {
+ struct spi_device *spi_device;
+ struct completion ready;
+ u8 *iobuf;
+};
+
+int tcm_tis_spi_transfer(struct device *dev, u32 addr, u16 len,
+ u8 *in, const u8 *out)
+{
+ struct tcm_tis_spi_phy *phy = dev_get_drvdata(dev);
+ int ret = 0;
+ struct spi_message m;
+ struct spi_transfer spi_xfer;
+ u8 transfer_len;
+
+ tcm_dbg("TCM-dbg: %s, addr: 0x%x, len: %x, %s\n",
+ __func__, addr, len, (in) ? "in" : "out");
+
+ spi_bus_lock(phy->spi_device->master);
+
+ /* set gpio1_a5 to LOW */
+ if (is_ft_all() && (phy->spi_device->chip_select == 0)) {
+ iowrite32(0x0, gpio1_a5);
+ }
+
+ while (len) {
+ transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
+
+ phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
+ phy->iobuf[1] = 0xd4;
+ phy->iobuf[2] = addr >> 8;
+ phy->iobuf[3] = addr;
+
+ memset(&spi_xfer, 0, sizeof(spi_xfer));
+ spi_xfer.tx_buf = phy->iobuf;
+ spi_xfer.rx_buf = phy->iobuf;
+ spi_xfer.len = 4;
+ spi_xfer.cs_change = 1;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&spi_xfer, &m);
+ ret = spi_sync_locked(phy->spi_device, &m);
+ if (ret < 0)
+ goto exit;
+
+ spi_xfer.cs_change = 0;
+ spi_xfer.len = transfer_len;
+ spi_xfer.delay_usecs = 5;
+
+ if (in) {
+ spi_xfer.tx_buf = NULL;
+ } else if (out) {
+ spi_xfer.rx_buf = NULL;
+ memcpy(phy->iobuf, out, transfer_len);
+ out += transfer_len;
+ }
+
+ spi_message_init(&m);
+ spi_message_add_tail(&spi_xfer, &m);
+ reinit_completion(&phy->ready);
+ ret = spi_sync_locked(phy->spi_device, &m);
+ if (ret < 0)
+ goto exit;
+
+ if (in) {
+ memcpy(in, phy->iobuf, transfer_len);
+ in += transfer_len;
+ }
+
+ len -= transfer_len;
+ }
+
+exit:
+ /* set gpio1_a5 to HIGH */
+ if (is_ft_all() && (phy->spi_device->chip_select == 0)) {
+ iowrite32(0x20, gpio1_a5);
+ }
+
+ spi_bus_unlock(phy->spi_device->master);
+ tcm_dbg("TCM-dbg: ret: %d\n", ret);
+ return ret;
+}
+
+static int tcm_tis_read8(struct device *dev,
+ u32 addr, u16 len, u8 *result)
+{
+ return tcm_tis_spi_transfer(dev, addr, len, result, NULL);
+}
+
+static int tcm_tis_write8(struct device *dev,
+ u32 addr, u16 len, u8 *value)
+{
+ return tcm_tis_spi_transfer(dev, addr, len, NULL, value);
+}
+
+static int tcm_tis_readb(struct device *dev, u32 addr, u8 *value)
+{
+ return tcm_tis_read8(dev, addr, sizeof(u8), value);
+}
+
+static int tcm_tis_writeb(struct device *dev, u32 addr, u8 value)
+{
+ return tcm_tis_write8(dev, addr, sizeof(u8), &value);
+}
+
+static int tcm_tis_readl(struct device *dev, u32 addr, u32 *result)
+{
+ int rc;
+ __le32 result_le;
+
+ rc = tcm_tis_read8(dev, addr, sizeof(u32), (u8 *)&result_le);
+ tcm_dbg("TCM-dbg: result_le: 0x%x\n", result_le);
+ if (!rc)
+ *result = le32_to_cpu(result_le);
+
+ return rc;
+}
+
+static int tcm_tis_writel(struct device *dev, u32 addr, u32 value)
+{
+ int rc;
+ __le32 value_le;
+
+ value_le = cpu_to_le32(value);
+ rc = tcm_tis_write8(dev, addr, sizeof(u32), (u8 *)&value_le);
+
+ return rc;
+}
+
+static int request_locality(struct tcm_chip *chip, int l);
+static void release_locality(struct tcm_chip *chip, int l, int force);
+static void cleanup_tis(void)
+{
+ int ret;
+ u32 inten;
+ struct tcm_vendor_specific *i, *j;
+ struct tcm_chip *chip;
+
+ spin_lock(&tis_lock);
+ list_for_each_entry_safe(i, j, &tis_chips, list) {
+ chip = to_tcm_chip(i);
+ ret = tcm_tis_readl(chip->dev,
+ TCM_INT_ENABLE(chip->vendor.locality), &inten);
+ if (ret < 0)
+ return;
+
+ tcm_tis_writel(chip->dev, TCM_INT_ENABLE(chip->vendor.locality),
+ ~TCM_GLOBAL_INT_ENABLE & inten);
+ release_locality(chip, chip->vendor.locality, 1);
+ }
+ spin_unlock(&tis_lock);
+}
+
+static void tcm_tis_init(struct tcm_chip *chip)
+{
+ int ret;
+ u8 rid;
+ u32 vendor, intfcaps;
+
+ ret = tcm_tis_readl(chip->dev, TCM_DID_VID(0), &vendor);
+
+ if ((vendor & 0xffff) != 0x19f5 && (vendor & 0xffff) != 0x1B4E)
+ pr_info("there is no Nationz TCM on you computer\n");
+
+ ret = tcm_tis_readb(chip->dev, TCM_RID(0), &rid);
+ if (ret < 0)
+ return;
+ pr_info("kylin: 2019-09-21 1.2 TCM (device-id 0x%X, rev-id %d)\n",
+ vendor >> 16, rid);
+
+ /* Figure out the capabilities */
+ ret = tcm_tis_readl(chip->dev,
+ TCM_INTF_CAPS(chip->vendor.locality), &intfcaps);
+ if (ret < 0)
+ return;
+
+ if (request_locality(chip, 0) != 0)
+ pr_err("tcm request_locality err\n");
+
+ atomic_set(&chip->data_pending, 0);
+}
+
+static void tcm_handle_err(struct tcm_chip *chip)
+{
+ cleanup_tis();
+ tcm_tis_init(chip);
+}
+
+static bool check_locality(struct tcm_chip *chip, int l)
+{
+ int ret;
+ u8 access;
+
+ ret = tcm_tis_readb(chip->dev, TCM_ACCESS(l), &access);
+ tcm_dbg("TCM-dbg: access: 0x%x\n", access);
+ if (ret < 0)
+ return false;
+
+ if ((access & (TCM_ACCESS_ACTIVE_LOCALITY | TCM_ACCESS_VALID)) ==
+ (TCM_ACCESS_ACTIVE_LOCALITY | TCM_ACCESS_VALID)) {
+ chip->vendor.locality = l;
+ return true;
+ }
+
+ return false;
+}
+
+static int request_locality(struct tcm_chip *chip, int l)
+{
+ unsigned long stop;
+
+ if (check_locality(chip, l))
+ return l;
+
+ tcm_tis_writeb(chip->dev, TCM_ACCESS(l), TCM_ACCESS_REQUEST_USE);
+
+ /* wait for burstcount */
+ stop = jiffies + chip->vendor.timeout_a;
+ do {
+ if (check_locality(chip, l))
+ return l;
+ msleep(TCM_TIMEOUT);
+ } while (time_before(jiffies, stop));
+
+ return -1;
+}
+
+static void release_locality(struct tcm_chip *chip, int l, int force)
+{
+ int ret;
+ u8 access;
+
+ ret = tcm_tis_readb(chip->dev, TCM_ACCESS(l), &access);
+ if (ret < 0)
+ return;
+ if (force || (access & (TCM_ACCESS_REQUEST_PENDING | TCM_ACCESS_VALID)) ==
+ (TCM_ACCESS_REQUEST_PENDING | TCM_ACCESS_VALID))
+ tcm_tis_writeb(chip->dev,
+ TCM_ACCESS(l), TCM_ACCESS_ACTIVE_LOCALITY);
+}
+
+static u8 tcm_tis_status(struct tcm_chip *chip)
+{
+ int ret;
+ u8 status;
+
+ ret = tcm_tis_readb(chip->dev,
+ TCM_STS(chip->vendor.locality), &status);
+ tcm_dbg("TCM-dbg: status: 0x%x\n", status);
+ if (ret < 0)
+ return 0;
+
+ return status;
+}
+
+static void tcm_tis_ready(struct tcm_chip *chip)
+{
+ /* this causes the current command to be aboreted */
+ tcm_tis_writeb(chip->dev, TCM_STS(chip->vendor.locality),
+ TCM_STS_COMMAND_READY);
+}
+
+static int get_burstcount(struct tcm_chip *chip)
+{
+ int ret;
+ unsigned long stop;
+ u8 tmp, tmp1;
+ int burstcnt = 0;
+
+ /* wait for burstcount */
+ /* which timeout value, spec has 2 answers (c & d) */
+ stop = jiffies + chip->vendor.timeout_d;
+ do {
+ ret = tcm_tis_readb(chip->dev,
+ TCM_STS(chip->vendor.locality) + 1,
+ &tmp);
+ tcm_dbg("TCM-dbg: burstcnt: 0x%x\n", burstcnt);
+ if (ret < 0)
+ return -EINVAL;
+ ret = tcm_tis_readb(chip->dev,
+ (TCM_STS(chip->vendor.locality) + 2),
+ &tmp1);
+ tcm_dbg("TCM-dbg: burstcnt: 0x%x\n", burstcnt);
+ if (ret < 0)
+ return -EINVAL;
+
+ burstcnt = tmp | (tmp1 << 8);
+ if (burstcnt)
+ return burstcnt;
+ msleep(TCM_TIMEOUT);
+ } while (time_before(jiffies, stop));
+
+ return -EBUSY;
+}
+
+static int wait_for_stat(struct tcm_chip *chip, u8 mask,
+ unsigned long timeout,
+ wait_queue_head_t *queue)
+{
+ unsigned long stop;
+ u8 status;
+
+ /* check current status */
+ status = tcm_tis_status(chip);
+ if ((status & mask) == mask)
+ return 0;
+
+ stop = jiffies + timeout;
+ do {
+ msleep(TCM_TIMEOUT);
+ status = tcm_tis_status(chip);
+ if ((status & mask) == mask)
+ return 0;
+ } while (time_before(jiffies, stop));
+
+ return -ETIME;
+}
+
+static int recv_data(struct tcm_chip *chip, u8 *buf, size_t count)
+{
+ int ret;
+ int size = 0, burstcnt;
+
+ while (size < count && wait_for_stat(chip,
+ TCM_STS_DATA_AVAIL | TCM_STS_VALID,
+ chip->vendor.timeout_c,
+ &chip->vendor.read_queue) == 0) {
+ burstcnt = get_burstcount(chip);
+
+ if (burstcnt < 0) {
+ dev_err(chip->dev, "Unable to read burstcount\n");
+ return burstcnt;
+ }
+
+ for (; burstcnt > 0 && size < count; burstcnt--) {
+ ret = tcm_tis_readb(chip->dev,
+ TCM_DATA_FIFO(chip->vendor.locality),
+ &buf[size]);
+ tcm_dbg("TCM-dbg: buf[%d]: 0x%x\n", size, buf[size]);
+ size++;
+ }
+ }
+
+ return size;
+}
+
+static int tcm_tis_recv(struct tcm_chip *chip, u8 *buf, size_t count)
+{
+ int size = 0;
+ int expected, status;
+ unsigned long stop;
+
+ if (count < TCM_HEADER_SIZE) {
+ dev_err(chip->dev, "read size is to small: %d\n", (u32)(count));
+ size = -EIO;
+ goto out;
+ }
+
+ /* read first 10 bytes, including tag, paramsize, and result */
+ size = recv_data(chip, buf, TCM_HEADER_SIZE);
+ if (size < TCM_HEADER_SIZE) {
+ dev_err(chip->dev, "Unable to read header\n");
+ goto out;
+ }
+
+ expected = be32_to_cpu(*(__be32 *)(buf + 2));
+ if (expected > count) {
+ dev_err(chip->dev, "Expected data count\n");
+ size = -EIO;
+ goto out;
+ }
+
+ size += recv_data(chip, &buf[TCM_HEADER_SIZE],
+ expected - TCM_HEADER_SIZE);
+ if (size < expected) {
+ dev_err(chip->dev, "Unable to read remainder of result\n");
+ size = -ETIME;
+ goto out;
+ }
+
+ wait_for_stat(chip, TCM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+
+ stop = jiffies + chip->vendor.timeout_c;
+ do {
+ msleep(TCM_TIMEOUT);
+ status = tcm_tis_status(chip);
+ if ((status & TCM_STS_DATA_AVAIL) == 0)
+ break;
+
+ } while (time_before(jiffies, stop));
+
+ status = tcm_tis_status(chip);
+ if (status & TCM_STS_DATA_AVAIL) { /* retry? */
+ dev_err(chip->dev, "Error left over data\n");
+ size = -EIO;
+ goto out;
+ }
+
+out:
+ tcm_tis_ready(chip);
+ release_locality(chip, chip->vendor.locality, 0);
+ if (size < 0)
+ tcm_handle_err(chip);
+ return size;
+}
+
+/*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tcm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+static int tcm_tis_send(struct tcm_chip *chip, u8 *buf, size_t len)
+{
+ int rc, status, burstcnt;
+ size_t count = 0;
+ u32 ordinal;
+ unsigned long stop;
+ int send_again = 0;
+
+tcm_tis_send_again:
+ count = 0;
+ if (request_locality(chip, 0) < 0) {
+ dev_err(chip->dev, "send, tcm is busy\n");
+ return -EBUSY;
+ }
+ status = tcm_tis_status(chip);
+
+ if ((status & TCM_STS_COMMAND_READY) == 0) {
+ tcm_tis_ready(chip);
+ if (wait_for_stat(chip, TCM_STS_COMMAND_READY,
+ chip->vendor.timeout_b, &chip->vendor.int_queue) < 0) {
+ dev_err(chip->dev, "send, tcm wait time out1\n");
+ rc = -ETIME;
+ goto out_err;
+ }
+ }
+
+ while (count < len - 1) {
+ burstcnt = get_burstcount(chip);
+ if (burstcnt < 0) {
+ dev_err(chip->dev, "Unable to read burstcount\n");
+ rc = burstcnt;
+ goto out_err;
+ }
+ for (; burstcnt > 0 && count < len - 1; burstcnt--) {
+ tcm_tis_writeb(chip->dev,
+ TCM_DATA_FIFO(chip->vendor.locality), buf[count]);
+ count++;
+ }
+
+ wait_for_stat(chip, TCM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ }
+
+ /* write last byte */
+ tcm_tis_writeb(chip->dev,
+ TCM_DATA_FIFO(chip->vendor.locality), buf[count]);
+
+ wait_for_stat(chip, TCM_STS_VALID,
+ chip->vendor.timeout_c, &chip->vendor.int_queue);
+ stop = jiffies + chip->vendor.timeout_c;
+ do {
+ msleep(TCM_TIMEOUT);
+ status = tcm_tis_status(chip);
+ if ((status & TCM_STS_DATA_EXPECT) == 0)
+ break;
+
+ } while (time_before(jiffies, stop));
+
+ if ((status & TCM_STS_DATA_EXPECT) != 0) {
+ dev_err(chip->dev, "send, tcm expect data\n");
+ rc = -EIO;
+ goto out_err;
+ }
+
+ /* go and do it */
+ tcm_tis_writeb(chip->dev, TCM_STS(chip->vendor.locality), TCM_STS_GO);
+
+ ordinal = be32_to_cpu(*((__be32 *)(buf + 6)));
+ if (wait_for_stat(chip, TCM_STS_DATA_AVAIL | TCM_STS_VALID,
+ tcm_calc_ordinal_duration(chip, ordinal),
+ &chip->vendor.read_queue) < 0) {
+ dev_err(chip->dev, "send, tcm wait time out2\n");
+ rc = -ETIME;
+ goto out_err;
+ }
+
+ return len;
+
+out_err:
+ tcm_tis_ready(chip);
+ release_locality(chip, chip->vendor.locality, 0);
+ tcm_handle_err(chip);
+ if (send_again++ < 3) {
+ goto tcm_tis_send_again;
+ }
+
+ dev_err(chip->dev, "kylin send, err: %d\n", rc);
+ return rc;
+}
+
+static struct file_operations tis_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tcm_open,
+ .read = tcm_read,
+ .write = tcm_write,
+ .release = tcm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tcm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tcm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tcm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tcm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tcm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tcm_show_temp_deactivated,
+ NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tcm_show_caps, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tcm_store_cancel);
+
+static struct attribute *tis_attrs[] = {
+ &dev_attr_pubek.attr,
+ &dev_attr_pcrs.attr,
+ &dev_attr_enabled.attr,
+ &dev_attr_active.attr,
+ &dev_attr_owned.attr,
+ &dev_attr_temp_deactivated.attr,
+ &dev_attr_caps.attr,
+ &dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group tis_attr_grp = {
+ .attrs = tis_attrs
+};
+
+static struct tcm_vendor_specific tcm_tis = {
+ .status = tcm_tis_status,
+ .recv = tcm_tis_recv,
+ .send = tcm_tis_send,
+ .cancel = tcm_tis_ready,
+ .req_complete_mask = TCM_STS_DATA_AVAIL | TCM_STS_VALID,
+ .req_complete_val = TCM_STS_DATA_AVAIL | TCM_STS_VALID,
+ .req_canceled = TCM_STS_COMMAND_READY,
+ .attr_group = &tis_attr_grp,
+ .miscdev = {
+ .fops = &tis_ops,
+ },
+};
+
+static struct tcm_chip *chip;
+static int tcm_tis_spi_probe(struct spi_device *spi)
+{
+ int ret;
+ u8 revid;
+ u32 vendor, intfcaps;
+ struct tcm_tis_spi_phy *phy;
+ struct chip_data *spi_chip;
+
+ pr_info("TCM(ky): __func__(v=%d) ..\n",
+ 10);
+
+ tcm_dbg("TCM-dbg: %s/%d, enter\n", __func__, __LINE__);
+ phy = devm_kzalloc(&spi->dev, sizeof(struct tcm_tis_spi_phy),
+ GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ phy->iobuf = devm_kmalloc(&spi->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
+ if (!phy->iobuf)
+ return -ENOMEM;
+
+ phy->spi_device = spi;
+ init_completion(&phy->ready);
+
+ tcm_dbg("TCM-dbg: %s/%d\n", __func__, __LINE__);
+ /* init spi dev */
+ spi->chip_select = 0; /* cs0 */
+ spi->mode = SPI_MODE_0;
+ spi->bits_per_word = 8;
+ spi->max_speed_hz = spi->max_speed_hz ? : 24000000;
+ spi_setup(spi);
+
+ spi_chip = spi_get_ctldata(spi);
+ if (!spi_chip) {
+ pr_err("There was wrong in spi master\n");
+ return -ENODEV;
+ }
+ /* tcm does not support interrupt mode, we use poll mode instead. */
+ spi_chip->poll_mode = 1;
+
+ tcm_dbg("TCM-dbg: %s/%d\n", __func__, __LINE__);
+ /* regiter tcm hw */
+ chip = tcm_register_hardware(&spi->dev, &tcm_tis);
+ if (!chip) {
+ dev_err(chip->dev, "tcm register hardware err\n");
+ return -ENODEV;
+ }
+
+ dev_set_drvdata(chip->dev, phy);
+
+ /**
+ * phytium2000a4 spi controller's clk clk level is unstable,
+ * so it is solved by using the low level of gpio output.
+ **/
+ if (is_ft_all() && (spi->chip_select == 0)) {
+ /* reuse conf reg base */
+ reuse_conf_reg = ioremap(REUSE_CONF_REG_BASE, 0x10);
+ if (!reuse_conf_reg) {
+ dev_err(&spi->dev, "Failed to ioremap reuse conf reg\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ /* gpio1 a5 base addr */
+ gpio1_a5 = ioremap(REUSE_GPIO1_A5_BASE, 0x10);
+ if (!gpio1_a5) {
+ dev_err(&spi->dev, "Failed to ioremap gpio1 a5\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ /* reuse cs0 to gpio1_a5 */
+ iowrite32((ioread32(reuse_conf_reg) | 0xFFFF0) & 0xFFF9004F,
+ reuse_conf_reg);
+ /* set gpio1 a5 to output */
+ iowrite32(0x20, gpio1_a5 + 0x4);
+ }
+
+ tcm_dbg("TCM-dbg: %s/%d\n",
+ __func__, __LINE__);
+ ret = tcm_tis_readl(chip->dev, TCM_DID_VID(0), &vendor);
+ if (ret < 0)
+ goto out_err;
+
+ tcm_dbg("TCM-dbg: %s/%d, vendor: 0x%x\n",
+ __func__, __LINE__, vendor);
+ if ((vendor & 0xffff) != 0x19f5 && (vendor & 0xffff) != 0x1B4E) {
+ dev_err(chip->dev, "there is no Nationz TCM on you computer\n");
+ goto out_err;
+ }
+
+ ret = tcm_tis_readb(chip->dev, TCM_RID(0), &revid);
+ tcm_dbg("TCM-dbg: %s/%d, revid: 0x%x\n",
+ __func__, __LINE__, revid);
+ if (ret < 0)
+ goto out_err;
+ dev_info(chip->dev, "kylin: 2019-09-21 1.2 TCM "
+ "(device-id 0x%X, rev-id %d)\n",
+ vendor >> 16, revid);
+
+ /* Default timeouts */
+ chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+ chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+ tcm_dbg("TCM-dbg: %s/%d\n",
+ __func__, __LINE__);
+ /* Figure out the capabilities */
+ ret = tcm_tis_readl(chip->dev,
+ TCM_INTF_CAPS(chip->vendor.locality), &intfcaps);
+ if (ret < 0)
+ goto out_err;
+
+ tcm_dbg("TCM-dbg: %s/%d, intfcaps: 0x%x\n",
+ __func__, __LINE__, intfcaps);
+ if (request_locality(chip, 0) != 0) {
+ dev_err(chip->dev, "tcm request_locality err\n");
+ ret = -ENODEV;
+ goto out_err;
+ }
+
+ INIT_LIST_HEAD(&chip->vendor.list);
+ spin_lock(&tis_lock);
+ list_add(&chip->vendor.list, &tis_chips);
+ spin_unlock(&tis_lock);
+
+ tcm_get_timeouts(chip);
+ tcm_startup(chip);
+
+ tcm_dbg("TCM-dbg: %s/%d, exit\n", __func__, __LINE__);
+ return 0;
+
+out_err:
+ if (is_ft_all()) {
+ if (reuse_conf_reg)
+ iounmap(reuse_conf_reg);
+ if (gpio1_a5)
+ iounmap(gpio1_a5);
+ }
+ tcm_dbg("TCM-dbg: %s/%d, error\n", __func__, __LINE__);
+ dev_set_drvdata(chip->dev, chip);
+ tcm_remove_hardware(chip->dev);
+
+ return ret;
+}
+
+static int tcm_tis_spi_remove(struct spi_device *dev)
+{
+ if (is_ft_all()) {
+ if (reuse_conf_reg)
+ iounmap(reuse_conf_reg);
+ if (gpio1_a5)
+ iounmap(gpio1_a5);
+ }
+
+ dev_info(&dev->dev, "%s\n", __func__);
+ dev_set_drvdata(chip->dev, chip);
+ tcm_remove_hardware(&dev->dev);
+
+ return 0;
+}
+
+static const struct acpi_device_id tcm_tis_spi_acpi_match[] = {
+ {"TCMS0001", 0},
+ {"SMO0768", 0},
+ {"ZIC0601", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, tcm_tis_spi_acpi_match);
+
+static const struct spi_device_id tcm_tis_spi_id_table[] = {
+ {"SMO0768", 0},
+ {"ZIC0601", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, tcm_tis_spi_id_table);
+
+static struct spi_driver tcm_tis_spi_drv = {
+ .driver = {
+ .name = "tcm_tis_spi",
+ .acpi_match_table = ACPI_PTR(tcm_tis_spi_acpi_match),
+ },
+ .id_table = tcm_tis_spi_id_table,
+ .probe = tcm_tis_spi_probe,
+ .remove = tcm_tis_spi_remove,
+};
+
+#if 1
+module_spi_driver(tcm_tis_spi_drv);
+#else/*0*/
+
+static int __init __spi_driver_init(void)
+{
+ pr_info("TCM(ky): __init __func__(ver=%2d)\n",
+ 10);
+ return spi_register_driver(&tcm_tis_spi_drv);
+}
+
+static void __exit __spi_driver_exit(void)
+{
+ pr_info("TCM(ky): __exit __func__\n");
+ spi_unregister_driver(&tcm_tis_spi_drv);
+}
+
+module_init(__spi_driver_init);
+module_exit(__spi_driver_exit);
+#endif/*0*/
+
+MODULE_AUTHOR("xiongxin<xiongxin(a)tj.kylinos.cn>");
+MODULE_DESCRIPTION("TCM Driver Base Spi");
+MODULE_VERSION("6.1.0.2");
+MODULE_LICENSE("GPL");
--
2.23.0
1
1

23 Feb '21
1
0

23 Feb '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
Introducing a feature of CPU PARK in order to save time
of cpus down and up during kexec, which may cost 250ms of
per cpu's down and 30ms of up.
As a result, for 128 cores, it costs more than 30 seconds
to down and up cpus during kexec. Think about 256 cores and more.
CPU PARK is a state that cpu power-on and staying in spin loop, polling
for exit chances, such as writing exit address.
Reserving a block of memory, to fill with cpu park text section,
exit address and park-magic-flag of each cpu. In implementation,
reserved one page for one cpu core.
Cpus going to park state instead of down in machine_shutdown().
Cpus going out of park state in smp_init instead of brought up.
One of cpu park sections in pre-reserved memory blocks,:
+--------------+
+ exit address +
+--------------+
+ park magic +
+--------------+
+ park codes +
+ . +
+ . +
+ . +
+--------------+
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/arm64/Kconfig | 12 ++
arch/arm64/include/asm/kexec.h | 6 +
arch/arm64/include/asm/smp.h | 15 +++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/cpu-park.S | 59 ++++++++++
arch/arm64/kernel/machine_kexec.c | 2 +-
arch/arm64/kernel/process.c | 4 +
arch/arm64/kernel/smp.c | 229 ++++++++++++++++++++++++++++++++++++++
arch/arm64/mm/init.c | 55 +++++++++
9 files changed, 382 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/cpu-park.S
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b9c5654..0885668 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -345,6 +345,18 @@ config KASAN_SHADOW_OFFSET
default 0xeffffff900000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
default 0xffffffffffffffff
+config ARM64_CPU_PARK
+ bool "Support CPU PARK on kexec"
+ depends on SMP
+ depends on KEXEC_CORE
+ help
+ This enables support for CPU PARK feature in
+ order to save time of cpu down to up.
+ CPU park is a state through kexec, spin loop
+ instead of cpu die before jumping to new kernel,
+ jumping out from loop to new kernel entry in
+ smp_init.
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 79909ae..a133889 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -36,6 +36,11 @@
#define CRASH_ADDR_HIGH_MAX MEMBLOCK_ALLOC_ACCESSIBLE
+#ifdef CONFIG_ARM64_CPU_PARK
+/* CPU park state flag: "park" */
+#define PARK_MAGIC 0x7061726b
+#endif
+
#ifndef __ASSEMBLY__
/**
@@ -104,6 +109,7 @@ static inline void crash_post_resume(void) {}
#ifdef CONFIG_KEXEC_CORE
extern void __init reserve_crashkernel(void);
#endif
+void machine_kexec_mask_interrupts(void);
#ifdef CONFIG_KEXEC_FILE
#define ARCH_HAS_KIMAGE_ARCH
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 2e7f529..8c5d2d6 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -145,6 +145,21 @@ bool cpus_are_stuck_in_kernel(void);
extern void crash_smp_send_stop(void);
extern bool smp_crash_stop_failed(void);
+#ifdef CONFIG_ARM64_CPU_PARK
+#define PARK_SECTION_SIZE 1024
+struct cpu_park_info {
+ /* Physical address of reserved park memory. */
+ unsigned long start;
+ /* park reserve mem len should be PARK_SECTION_SIZE * NR_CPUS */
+ unsigned long len;
+ /* Virtual address of reserved park memory. */
+ unsigned long start_v;
+};
+extern struct cpu_park_info park_info;
+extern void enter_cpu_park(unsigned long text, unsigned long exit);
+extern void do_cpu_park(unsigned long exit);
+extern int kexec_smp_send_park(void);
+#endif
#endif /* ifndef __ASSEMBLY__ */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2621d5c..60478d2 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o
obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o \
cpu-reset.o
+obj-$(CONFIG_ARM64_CPU_PARK) += cpu-park.o
obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_image.o
obj-$(CONFIG_ARM64_RELOC_TEST) += arm64-reloc-test.o
arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o
diff --git a/arch/arm64/kernel/cpu-park.S b/arch/arm64/kernel/cpu-park.S
new file mode 100644
index 0000000..10c685c
--- /dev/null
+++ b/arch/arm64/kernel/cpu-park.S
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * CPU park routines
+ *
+ * Copyright (C) 2020 Huawei Technologies., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/kexec.h>
+#include <asm/sysreg.h>
+#include <asm/virt.h>
+
+.text
+.pushsection .idmap.text, "awx"
+
+/* cpu park helper in idmap section */
+SYM_CODE_START(enter_cpu_park)
+ /* Clear sctlr_el1 flags. */
+ mrs x12, sctlr_el1
+ mov_q x13, SCTLR_ELx_FLAGS
+ bic x12, x12, x13
+ pre_disable_mmu_workaround
+ msr sctlr_el1, x12 /* disable mmu */
+ isb
+
+ mov x18, x0
+ mov x0, x1 /* secondary_entry addr */
+ br x18 /* call do_cpu_park of each cpu */
+SYM_CODE_END(enter_cpu_park)
+
+.popsection
+
+SYM_CODE_START(do_cpu_park)
+ ldr x18, =PARK_MAGIC /* magic number "park" */
+ add x1, x0, #8
+ str x18, [x1] /* set on-park flag */
+ dc civac, x1 /* flush cache of "park" */
+ dsb nsh
+ isb
+
+.Lloop:
+ wfe
+ isb
+ ldr x19, [x0]
+ cmp x19, #0 /* test secondary_entry */
+ b.eq .Lloop
+
+ ic iallu /* invalidate the local I-cache */
+ dsb nsh
+ isb
+
+ br x19 /* jump to secondary_entry */
+SYM_CODE_END(do_cpu_park)
+
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index a0b144c..f47ce96 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -213,7 +213,7 @@ void machine_kexec(struct kimage *kimage)
BUG(); /* Should never get here. */
}
-static void machine_kexec_mask_interrupts(void)
+void machine_kexec_mask_interrupts(void)
{
unsigned int i;
struct irq_desc *desc;
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 73e3b32..10cffee 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -146,6 +146,10 @@ void arch_cpu_idle_dead(void)
*/
void machine_shutdown(void)
{
+#ifdef CONFIG_ARM64_CPU_PARK
+ if (kexec_smp_send_park() == 0)
+ return;
+#endif
smp_shutdown_nonboot_cpus(reboot_cpu);
}
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 18e9727..bc475d5 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -32,6 +32,8 @@
#include <linux/irq_work.h>
#include <linux/kernel_stat.h>
#include <linux/kexec.h>
+#include <linux/console.h>
+
#include <linux/kvm_host.h>
#include <asm/alternative.h>
@@ -93,6 +95,167 @@ static inline int op_cpu_kill(unsigned int cpu)
}
#endif
+#ifdef CONFIG_ARM64_CPU_PARK
+struct cpu_park_section {
+ unsigned long exit; /* exit address of park look */
+ unsigned long magic; /* maigc represent park state */
+ char text[0]; /* text section of park */
+};
+
+static int mmap_cpu_park_mem(void)
+{
+ if (!park_info.start)
+ return -ENOMEM;
+
+ if (park_info.start_v)
+ return 0;
+
+ park_info.start_v = (unsigned long)__ioremap(park_info.start,
+ park_info.len,
+ PAGE_KERNEL_EXEC);
+ if (!park_info.start_v) {
+ pr_warn("map park memory failed.");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static inline unsigned long cpu_park_section_v(unsigned int cpu)
+{
+ return park_info.start_v + PARK_SECTION_SIZE * (cpu - 1);
+}
+
+static inline unsigned long cpu_park_section_p(unsigned int cpu)
+{
+ return park_info.start + PARK_SECTION_SIZE * (cpu - 1);
+}
+
+/*
+ * Write the secondary_entry to exit section of park state.
+ * Then the secondary cpu will jump straight into the kernel
+ * by the secondary_entry.
+ */
+static int write_park_exit(unsigned int cpu)
+{
+ struct cpu_park_section *park_section;
+ unsigned long *park_exit;
+ unsigned long *park_text;
+
+ if (mmap_cpu_park_mem() != 0)
+ return -EPERM;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ park_exit = &park_section->exit;
+ park_text = (unsigned long *)park_section->text;
+ pr_debug("park_text 0x%lx : 0x%lx, do_cpu_park text 0x%lx : 0x%lx",
+ (unsigned long)park_text, *park_text,
+ (unsigned long)do_cpu_park,
+ *(unsigned long *)do_cpu_park);
+
+ /*
+ * Test first 8 bytes to determine
+ * whether needs to write cpu park exit.
+ */
+ if (*park_text == *(unsigned long *)do_cpu_park) {
+ writeq_relaxed(__pa_symbol(secondary_entry), park_exit);
+ __flush_dcache_area((__force void *)park_exit,
+ sizeof(unsigned long));
+ flush_icache_range((unsigned long)park_exit,
+ (unsigned long)(park_exit + 1));
+ sev();
+ dsb(sy);
+ isb();
+
+ pr_debug("Write cpu %u secondary entry 0x%lx to 0x%lx.",
+ cpu, *park_exit, (unsigned long)park_exit);
+ pr_info("Boot cpu %u from PARK state.", cpu);
+ return 0;
+ }
+
+ return -EPERM;
+}
+
+/* Install cpu park sections for the specific cpu. */
+static int install_cpu_park(unsigned int cpu)
+{
+ struct cpu_park_section *park_section;
+ unsigned long *park_exit;
+ unsigned long *park_magic;
+ unsigned long park_text_len;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ pr_debug("Install cpu park on cpu %u park exit 0x%lx park text 0x%lx",
+ cpu, (unsigned long)park_section,
+ (unsigned long)(park_section->text));
+
+ park_exit = &park_section->exit;
+ park_magic = &park_section->magic;
+ park_text_len = PARK_SECTION_SIZE - sizeof(struct cpu_park_section);
+
+ *park_exit = 0UL;
+ *park_magic = 0UL;
+ memcpy((void *)park_section->text, do_cpu_park, park_text_len);
+ __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE);
+
+ return 0;
+}
+
+static int uninstall_cpu_park(unsigned int cpu)
+{
+ unsigned long park_section;
+
+ if (mmap_cpu_park_mem() != 0)
+ return -EPERM;
+
+ park_section = cpu_park_section_v(cpu);
+ memset((void *)park_section, 0, PARK_SECTION_SIZE);
+ __flush_dcache_area((void *)park_section, PARK_SECTION_SIZE);
+
+ return 0;
+}
+
+static int cpu_wait_park(unsigned int cpu)
+{
+ long timeout;
+ struct cpu_park_section *park_section;
+
+ volatile unsigned long *park_magic;
+
+ park_section = (struct cpu_park_section *)cpu_park_section_v(cpu);
+ park_magic = &park_section->magic;
+
+ timeout = USEC_PER_SEC;
+ while (*park_magic != PARK_MAGIC && timeout--)
+ udelay(1);
+
+ if (timeout > 0)
+ pr_debug("cpu %u park done.", cpu);
+ else
+ pr_err("cpu %u park failed.", cpu);
+
+ return *park_magic == PARK_MAGIC;
+}
+
+static void cpu_park(unsigned int cpu)
+{
+ unsigned long park_section_p;
+ unsigned long park_exit_phy;
+ unsigned long do_park;
+ typeof(enter_cpu_park) *park;
+
+ park_section_p = cpu_park_section_p(cpu);
+ park_exit_phy = park_section_p;
+ pr_debug("Go to park cpu %u exit address 0x%lx", cpu, park_exit_phy);
+
+ do_park = park_section_p + sizeof(struct cpu_park_section);
+ park = (void *)__pa_symbol(enter_cpu_park);
+
+ cpu_install_idmap();
+ park(do_park, park_exit_phy);
+ unreachable();
+}
+#endif
/*
* Boot a secondary CPU, and assign it the specified idle task.
@@ -102,6 +265,10 @@ static int boot_secondary(unsigned int cpu, struct task_struct *idle)
{
const struct cpu_operations *ops = get_cpu_ops(cpu);
+#ifdef CONFIG_ARM64_CPU_PARK
+ if (write_park_exit(cpu) == 0)
+ return 0;
+#endif
if (ops->cpu_boot)
return ops->cpu_boot(cpu);
@@ -131,6 +298,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
return ret;
}
+#ifdef CONFIG_ARM64_CPU_PARK
+ uninstall_cpu_park(cpu);
+#endif
/*
* CPU was successfully started, wait for it to come online or
* time out.
@@ -844,10 +1014,30 @@ void arch_irq_work_raise(void)
static void local_cpu_stop(void)
{
+ int cpu;
+ const struct cpu_operations *ops = NULL;
+
set_cpu_online(smp_processor_id(), false);
local_daif_mask();
sdei_mask_local_cpu();
+
+#ifdef CONFIG_ARM64_CPU_PARK
+ /*
+ * Go to cpu park state.
+ * Otherwise go to cpu die.
+ */
+ cpu = smp_processor_id();
+ if (kexec_in_progress && park_info.start_v) {
+ machine_kexec_mask_interrupts();
+ cpu_park(cpu);
+
+ ops = get_cpu_ops(cpu);
+ if (ops && ops->cpu_die)
+ ops->cpu_die(cpu);
+ }
+#endif
+
cpu_park_loop();
}
@@ -1053,6 +1243,45 @@ void smp_send_stop(void)
sdei_mask_local_cpu();
}
+#ifdef CONFIG_ARM64_CPU_PARK
+int kexec_smp_send_park(void)
+{
+ unsigned long cpu;
+
+ if (WARN_ON(!kexec_in_progress)) {
+ pr_crit("%s called not in kexec progress.", __func__);
+ return -EPERM;
+ }
+
+ if (mmap_cpu_park_mem() != 0) {
+ pr_info("no cpuparkmem, goto normal way.");
+ return -EPERM;
+ }
+
+ local_irq_disable();
+
+ if (num_online_cpus() > 1) {
+ cpumask_t mask;
+
+ cpumask_copy(&mask, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), &mask);
+
+ for_each_cpu(cpu, &mask)
+ install_cpu_park(cpu);
+ smp_cross_call(&mask, IPI_CPU_STOP);
+
+ /* Wait for other CPUs to park */
+ for_each_cpu(cpu, &mask)
+ cpu_wait_park(cpu);
+ pr_info("smp park other cpus done\n");
+ }
+
+ sdei_mask_local_cpu();
+
+ return 0;
+}
+#endif
+
#ifdef CONFIG_KEXEC_CORE
void crash_smp_send_stop(void)
{
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 794f992..d01259c 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -236,6 +236,57 @@ static void __init fdt_enforce_memory_region(void)
memblock_add(usable_rgns[1].base, usable_rgns[1].size);
}
+#ifdef CONFIG_ARM64_CPU_PARK
+struct cpu_park_info park_info = {
+ .start = 0,
+ .len = PARK_SECTION_SIZE * NR_CPUS,
+ .start_v = 0,
+};
+
+static int __init parse_park_mem(char *p)
+{
+ if (!p)
+ return 0;
+
+ park_info.start = PAGE_ALIGN(memparse(p, NULL));
+ if (park_info.start == 0)
+ pr_info("cpu park mem params[%s]", p);
+
+ return 0;
+}
+early_param("cpuparkmem", parse_park_mem);
+
+static int __init reserve_park_mem(void)
+{
+ if (park_info.start == 0 || park_info.len == 0)
+ return 0;
+
+ park_info.start = PAGE_ALIGN(park_info.start);
+ park_info.len = PAGE_ALIGN(park_info.len);
+
+ if (!memblock_is_region_memory(park_info.start, park_info.len)) {
+ pr_warn("cannot reserve park mem: region is not memory!");
+ goto out;
+ }
+
+ if (memblock_is_region_reserved(park_info.start, park_info.len)) {
+ pr_warn("cannot reserve park mem: region overlaps reserved memory!");
+ goto out;
+ }
+
+ memblock_remove(park_info.start, park_info.len);
+ pr_info("cpu park mem reserved: 0x%016lx - 0x%016lx (%ld MB)",
+ park_info.start, park_info.start + park_info.len,
+ park_info.len >> 20);
+
+ return 0;
+out:
+ park_info.start = 0;
+ park_info.len = 0;
+ return -EINVAL;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -357,6 +408,10 @@ void __init arm64_memblock_init(void)
reserve_crashkernel();
+#ifdef CONFIG_ARM64_CPU_PARK
+ reserve_park_mem();
+#endif
+
reserve_elfcorehdr();
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
--
2.9.5
2
3

22 Feb '21
From: Sang Yan <sangyan(a)huawei.com>
hulk inclusion
category: feature
bugzilla: 48159
CVE: N/A
In normal kexec, relocating kernel may cost 5 ~ 10 seconds, to
copy all segments from vmalloced memory to kernel boot memory,
because of disabled mmu.
We introduce quick kexec to save time of copying memory as above,
just like kdump(kexec on crash), by using reserved memory
"Quick Kexec".
Constructing quick kimage as the same as crash kernel,
then simply copy all segments of kimage to reserved memroy.
We also add this support in syscall kexec_load using flags
of KEXEC_QUICK.
Signed-off-by: Sang Yan <sangyan(a)huawei.com>
---
arch/Kconfig | 10 ++++++++++
include/linux/ioport.h | 1 +
include/linux/kexec.h | 11 ++++++++++-
include/uapi/linux/kexec.h | 1 +
kernel/kexec.c | 10 ++++++++++
kernel/kexec_core.c | 42 +++++++++++++++++++++++++++++++++---------
6 files changed, 65 insertions(+), 10 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 2592b4b..7811eee 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -18,6 +18,16 @@ config KEXEC_CORE
select CRASH_CORE
bool
+config QUICK_KEXEC
+ bool "Support for quick kexec"
+ depends on KEXEC_CORE
+ help
+ It uses pre-reserved memory to accelerate kexec, just like
+ crash kexec, loads new kernel and initrd to reserved memory,
+ and boots new kernel on that memory. It will save the time
+ of relocating kernel.
+
+
config KEXEC_ELF
bool
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 5135d4b..84a716f 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -139,6 +139,7 @@ enum {
IORES_DESC_DEVICE_PRIVATE_MEMORY = 6,
IORES_DESC_RESERVED = 7,
IORES_DESC_SOFT_RESERVED = 8,
+ IORES_DESC_QUICK_KEXEC = 9,
};
/*
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index f301f2f..7fff410 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -269,9 +269,10 @@ struct kimage {
unsigned long control_page;
/* Flags to indicate special processing */
- unsigned int type : 1;
+ unsigned int type : 2;
#define KEXEC_TYPE_DEFAULT 0
#define KEXEC_TYPE_CRASH 1
+#define KEXEC_TYPE_QUICK 2
unsigned int preserve_context : 1;
/* If set, we are using file mode kexec syscall */
unsigned int file_mode:1;
@@ -331,6 +332,11 @@ extern int kexec_load_disabled;
#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT)
#endif
+#ifdef CONFIG_QUICK_KEXEC
+#undef KEXEC_FLAGS
+#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_QUICK)
+#endif
+
/* List of defined/legal kexec file flags */
#define KEXEC_FILE_FLAGS (KEXEC_FILE_UNLOAD | KEXEC_FILE_ON_CRASH | \
KEXEC_FILE_NO_INITRAMFS)
@@ -338,6 +344,9 @@ extern int kexec_load_disabled;
/* Location of a reserved region to hold the crash kernel.
*/
extern note_buf_t __percpu *crash_notes;
+#ifdef CONFIG_QUICK_KEXEC
+extern struct resource quick_kexec_res;
+#endif
/* flag to track if kexec reboot is in progress */
extern bool kexec_in_progress;
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h
index 05669c8..d891d80 100644
--- a/include/uapi/linux/kexec.h
+++ b/include/uapi/linux/kexec.h
@@ -12,6 +12,7 @@
/* kexec flags for different usage scenarios */
#define KEXEC_ON_CRASH 0x00000001
#define KEXEC_PRESERVE_CONTEXT 0x00000002
+#define KEXEC_QUICK 0x00000004
#define KEXEC_ARCH_MASK 0xffff0000
/*
diff --git a/kernel/kexec.c b/kernel/kexec.c
index c82c6c0..4acc909 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -44,6 +44,9 @@ static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
int ret;
struct kimage *image;
bool kexec_on_panic = flags & KEXEC_ON_CRASH;
+#ifdef CONFIG_QUICK_KEXEC
+ bool kexec_on_quick = flags & KEXEC_QUICK;
+#endif
if (kexec_on_panic) {
/* Verify we have a valid entry point */
@@ -69,6 +72,13 @@ static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
image->type = KEXEC_TYPE_CRASH;
}
+#ifdef CONFIG_QUICK_KEXEC
+ if (kexec_on_quick) {
+ image->control_page = quick_kexec_res.start;
+ image->type = KEXEC_TYPE_QUICK;
+ }
+#endif
+
ret = sanity_check_segment_list(image);
if (ret)
goto out_free_image;
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 2ca8875..c7e2aa2 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -53,6 +53,17 @@ note_buf_t __percpu *crash_notes;
/* Flag to indicate we are going to kexec a new kernel */
bool kexec_in_progress = false;
+/* Resource for quick kexec */
+#ifdef CONFIG_QUICK_KEXEC
+struct resource quick_kexec_res = {
+ .name = "Quick kexec",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
+ .desc = IORES_DESC_QUICK_KEXEC
+};
+#endif
+
int kexec_should_crash(struct task_struct *p)
{
/*
@@ -396,8 +407,9 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image,
return pages;
}
-static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
- unsigned int order)
+static struct page *kimage_alloc_special_control_pages(struct kimage *image,
+ unsigned int order,
+ unsigned long end)
{
/* Control pages are special, they are the intermediaries
* that are needed while we copy the rest of the pages
@@ -427,7 +439,7 @@ static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
size = (1 << order) << PAGE_SHIFT;
hole_start = (image->control_page + (size - 1)) & ~(size - 1);
hole_end = hole_start + size - 1;
- while (hole_end <= crashk_res.end) {
+ while (hole_end <= end) {
unsigned long i;
cond_resched();
@@ -462,7 +474,6 @@ static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
return pages;
}
-
struct page *kimage_alloc_control_pages(struct kimage *image,
unsigned int order)
{
@@ -473,8 +484,15 @@ struct page *kimage_alloc_control_pages(struct kimage *image,
pages = kimage_alloc_normal_control_pages(image, order);
break;
case KEXEC_TYPE_CRASH:
- pages = kimage_alloc_crash_control_pages(image, order);
+ pages = kimage_alloc_special_control_pages(image, order,
+ crashk_res.end);
+ break;
+#ifdef CONFIG_QUICK_KEXEC
+ case KEXEC_TYPE_QUICK:
+ pages = kimage_alloc_special_control_pages(image, order,
+ quick_kexec_res.end);
break;
+#endif
}
return pages;
@@ -830,11 +848,12 @@ static int kimage_load_normal_segment(struct kimage *image,
return result;
}
-static int kimage_load_crash_segment(struct kimage *image,
+static int kimage_load_special_segment(struct kimage *image,
struct kexec_segment *segment)
{
- /* For crash dumps kernels we simply copy the data from
- * user space to it's destination.
+ /*
+ * For crash dumps kernels and quick kexec kernels
+ * we simply copy the data from user space to it's destination.
* We do things a page at a time for the sake of kmap.
*/
unsigned long maddr;
@@ -908,8 +927,13 @@ int kimage_load_segment(struct kimage *image,
result = kimage_load_normal_segment(image, segment);
break;
case KEXEC_TYPE_CRASH:
- result = kimage_load_crash_segment(image, segment);
+ result = kimage_load_special_segment(image, segment);
break;
+#ifdef CONFIG_QUICK_KEXEC
+ case KEXEC_TYPE_QUICK:
+ result = kimage_load_special_segment(image, segment);
+ break;
+#endif
}
return result;
--
2.9.5
2
3
bugfix for 20.03 @ 2021/02/22
Aichun Li (7):
netpoll: remove dev argument from netpoll_send_skb_on_dev()
netpoll: move netpoll_send_skb() out of line
netpoll: netpoll_send_skb() returns transmit status
netpoll: accept NULL np argument in netpoll_send_skb()
bonding: add an option to specify a delay between peer notifications
bonding: fix value exported by Netlink for peer_notif_delay
bonding: add documentation for peer_notif_delay
Akilesh Kailash (1):
dm snapshot: flush merged data before committing metadata
Al Viro (2):
don't dump the threads that had been already exiting when zapped.
dump_common_audit_data(): fix racy accesses to ->d_name
Aleksandr Nogikh (1):
netem: fix zero division in tabledist
Alexander Duyck (1):
tcp: Set INET_ECN_xmit configuration in tcp_reinit_congestion_control
Alexander Lobakin (1):
skbuff: back tiny skbs with kmalloc() in __netdev_alloc_skb() too
Alexey Dobriyan (2):
proc: change ->nlink under proc_subdir_lock
proc: fix lookup in /proc/net subdirectories after setns(2)
Alexey Kardashevskiy (1):
serial_core: Check for port state when tty is in error state
Amit Cohen (1):
mlxsw: core: Fix use-after-free in mlxsw_emad_trans_finish()
Andy Shevchenko (2):
device property: Keep secondary firmware node secondary by type
device property: Don't clear secondary pointer for shared primary
firmware node
Antoine Tenart (6):
netfilter: bridge: reset skb->pkt_type after NF_INET_POST_ROUTING
traversal
net: ip6_gre: set dev->hard_header_len when using header_ops
net-sysfs: take the rtnl lock when storing xps_cpus
net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc
net-sysfs: take the rtnl lock when storing xps_rxqs
net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc
Ard Biesheuvel (3):
efivarfs: revert "fix memory leak in efivarfs_create()"
arm64, mm, efi: Account for GICv3 LPI tables in static memblock
reserve table
efi/arm: Revert "Defer persistent reservations until after
paging_init()"
Arjun Roy (1):
tcp: Prevent low rmem stalls with SO_RCVLOWAT.
Arnaldo Carvalho de Melo (1):
perf scripting python: Avoid declaring function pointers with a
visibility attribute
Axel Lin (1):
ASoC: msm8916-wcd-digital: Select REGMAP_MMIO to fix build error
Aya Levin (1):
net: ipv6: Validate GSO SKB before finish IPv6 processing
Bart Van Assche (1):
scsi: scsi_transport_spi: Set RQF_PM for domain validation commands
Bharat Gooty (1):
PCI: iproc: Fix out-of-bound array accesses
Bixuan Cui (2):
mmap: fix a compiling error for 'MAP_CHECKNODE'
powerpc: fix a compiling error for 'access_ok'
Bjorn Helgaas (1):
PCI: Bounds-check command-line resource alignment requests
Björn Töpel (1):
ixgbe: avoid premature Rx buffer reuse
Boqun Feng (1):
fcntl: Fix potential deadlock in send_sig{io, urg}()
Boris Protopopov (1):
Convert trailing spaces and periods in path components
Brian Foster (1):
xfs: flush new eof page on truncate to avoid post-eof corruption
Calum Mackay (1):
lockd: don't use interval-based rebinding over TCP
Chen Zhou (1):
selinux: Fix error return code in sel_ib_pkey_sid_slow()
Chenguangli (1):
scsi/hifc:Fix the bug that the system may be oops during unintall hifc
module.
Cheng Lin (1):
nfs_common: need lock during iterate through the list
Christoph Hellwig (2):
nbd: fix a block_device refcount leak in nbd_release
xfs: fix a missing unlock on error in xfs_fs_map_blocks
Chunguang Xu (1):
ext4: fix a memory leak of ext4_free_data
Chunyan Zhang (1):
tick/common: Touch watchdog in tick_unfreeze() on all CPUs
Colin Ian King (1):
PCI: Fix overflow in command-line resource alignment requests
Cong Wang (1):
erspan: fix version 1 check in gre_parse_header()
Damien Le Moal (1):
null_blk: Fix zone size initialization
Dan Carpenter (1):
futex: Don't enable IRQs unconditionally in put_pi_state()
Daniel Scally (1):
Revert "ACPI / resources: Use AE_CTRL_TERMINATE to terminate resources
walks"
Darrick J. Wong (12):
xfs: fix realtime bitmap/summary file truncation when growing rt
volume
xfs: don't free rt blocks when we're doing a REMAP bunmapi call
xfs: set xefi_discard when creating a deferred agfl free log intent
item
xfs: fix scrub flagging rtinherit even if there is no rt device
xfs: fix flags argument to rmap lookup when converting shared file
rmaps
xfs: set the unwritten bit in rmap lookup flags in
xchk_bmap_get_rmapextents
xfs: fix rmap key and record comparison functions
xfs: fix brainos in the refcount scrubber's rmap fragment processor
vfs: remove lockdep bogosity in __sb_start_write
xfs: fix the minrecs logic when dealing with inode root child blocks
xfs: strengthen rmap record flags checking
xfs: revert "xfs: fix rmap key and record comparison functions"
Dave Wysochanski (1):
NFS4: Fix use-after-free in trace_event_raw_event_nfs4_set_lock
Dexuan Cui (1):
ACPI: scan: Harden acpi_device_add() against device ID overflows
Dinghao Liu (4):
ext4: fix error handling code in add_new_gdb
net/mlx5e: Fix memleak in mlx5e_create_l2_table_groups
net/mlx5e: Fix two double free cases
netfilter: nf_nat: Fix memleak in nf_nat_init
Dongdong Wang (1):
lwt: Disable BH too in run_lwt_bpf()
Dongli Zhang (1):
page_frag: Recover from memory pressure
Douglas Gilbert (1):
sgl_alloc_order: fix memory leak
Eddy Wu (1):
fork: fix copy_process(CLONE_PARENT) race with the exiting
->real_parent
Eran Ben Elisha (1):
net/mlx5: Fix wrong address reclaim when command interface is down
Eric Auger (1):
vfio/pci: Move dummy_resources_list init in vfio_pci_probe()
Eric Biggers (1):
ext4: fix leaking sysfs kobject after failed mount
Eric Dumazet (4):
tcp: select sane initial rcvq_space.space for big MSS
net: avoid 32 x truesize under-estimation for tiny skbs
net_sched: avoid shift-out-of-bounds in tcindex_set_parms()
net_sched: reject silly cell_log in qdisc_get_rtab()
Fang Lijun (3):
arm64/ascend: mm: Add MAP_CHECKNODE flag to check node hugetlb
arm64/ascend: mm: Fix arm32 compile warnings
arm64/ascend: mm: Fix hugetlb check node error
Fangrui Song (1):
arm64: Change .weak to SYM_FUNC_START_WEAK_PI for
arch/arm64/lib/mem*.S
Florian Fainelli (1):
net: Have netpoll bring-up DSA management interface
Florian Westphal (4):
netfilter: nf_tables: avoid false-postive lockdep splat
netfilter: xt_RATEEST: reject non-null terminated string from
userspace
net: ip: always refragment ip defragmented packets
net: fix pmtu check in nopmtudisc mode
Gabriel Krisman Bertazi (2):
blk-cgroup: Fix memleak on error path
blk-cgroup: Pre-allocate tree node on blkg_conf_prep
George Spelvin (1):
random32: make prandom_u32() output unpredictable
Gerald Schaefer (1):
mm/userfaultfd: do not access vma->vm_mm after calling
handle_userfault()
Guillaume Nault (4):
ipv4: Fix tos mask in inet_rtm_getroute()
ipv4: Ignore ECN bits for fib lookups in fib_compute_spec_dst()
netfilter: rpfilter: mask ecn bits before fib lookup
udp: mask TOS bits in udp_v4_early_demux()
Hanjun Guo (1):
clocksource/drivers/arch_timer: Fix vdso_fix compile error for arm32
Hannes Reinecke (1):
dm: avoid filesystem lookup in dm_get_dev_t()
Hans de Goede (1):
ACPI: scan: Make acpi_bus_get_device() clear return pointer on error
Heiner Kallweit (1):
net: bridge: add missing counters to ndo_get_stats64 callback
Hoang Le (1):
tipc: fix NULL deref in tipc_link_xmit()
Huang Shijie (1):
lib/genalloc: fix the overflow when size is too big
Huang Ying (1):
mm: fix a race during THP splitting
Hugh Dickins (2):
mlock: fix unevictable_pgs event counts on THP
mm: fix check_move_unevictable_pages() on THP
Hui Wang (1):
ACPI: PNP: compare the string length in the matching_id()
Hyeongseok Kim (1):
dm verity: skip verity work if I/O error when system is shutting down
Ido Schimmel (2):
mlxsw: core: Fix memory leak on module removal
mlxsw: core: Use variable timeout for EMAD retries
Ilya Dryomov (1):
libceph: clear con->out_msg on Policy::stateful_server faults
Jakub Kicinski (1):
net: vlan: avoid leaks on register_vlan_dev() failures
Jamie Iles (1):
bonding: wait for sysfs kobject destruction before freeing struct
slave
Jan Kara (8):
ext4: Detect already used quota file early
ext4: fix bogus warning in ext4_update_dx_flag()
ext4: Protect superblock modifications with a buffer lock
ext4: fix deadlock with fs freezing and EA inodes
ext4: don't remount read-only with errors=continue on reboot
quota: Don't overflow quota file offsets
bfq: Fix computation of shallow depth
ext4: fix superblock checksum failure when setting password salt
Jann Horn (1):
mm, slub: consider rest of partial list if acquire_slab() fails
Jason A. Donenfeld (3):
netfilter: use actual socket sk rather than skb sk when routing harder
net: introduce skb_list_walk_safe for skb segment walking
net: skbuff: disambiguate argument and member for skb_list_walk_safe
helper
Jeff Dike (1):
virtio_net: Fix recursive call to cpus_read_lock()
Jens Axboe (1):
proc: don't allow async path resolution of /proc/self components
Jesper Dangaard Brouer (1):
netfilter: conntrack: fix reading nf_conntrack_buckets
Jessica Yu (1):
module: delay kobject uevent until after module init call
Jiri Olsa (2):
perf python scripting: Fix printable strings in python3 scripts
perf tools: Add missing swap for ino_generation
Johannes Thumshirn (1):
block: factor out requeue handling from dispatch code
Jonathan Cameron (1):
ACPI: Add out of bounds and numa_off protections to pxm_to_node()
Joseph Qi (1):
ext4: unlock xattr_sem properly in ext4_inline_data_truncate()
Jubin Zhong (1):
PCI: Fix pci_slot_release() NULL pointer dereference
Kaixu Xia (1):
ext4: correctly report "not supported" for {usr, grp}jquota when
!CONFIG_QUOTA
Keqian Zhu (1):
clocksource/drivers/arm_arch_timer: Correct fault programming of
CNTKCTL_EL1.EVNTI
Kirill Tkhai (1):
mm: move nr_deactivate accounting to shrink_active_list()
Lang Dai (1):
uio: free uio id after uio file node is freed
Lecopzer Chen (2):
kasan: fix unaligned address is unhandled in kasan_remove_zero_shadow
kasan: fix incorrect arguments passing in kasan_add_zero_shadow
Lee Duncan (1):
scsi: libiscsi: Fix NOP race condition
Lee Jones (1):
Fonts: Replace discarded const qualifier
Leo Yan (1):
perf lock: Don't free "lock_seq_stat" if read_count isn't zero
Leon Romanovsky (1):
net/mlx5: Properly convey driver version to firmware
Lijie (1):
config: enable CONFIG_NVME_MULTIPATH by default
Liu Shixin (3):
config: set default value of CONFIG_TEST_FREE_PAGES
mm: memcontrol: add struct mem_cgroup_extension
mm: fix kabi broken
Lorenzo Pieralisi (1):
asm-generic/io.h: Fix !CONFIG_GENERIC_IOMAP pci_iounmap()
implementation
Lu Jialin (1):
fs: fix files.usage bug when move tasks
Luc Van Oostenryck (1):
xsk: Fix xsk_poll()'s return type
Luo Meng (2):
ext4: fix invalid inode checksum
fail_function: Remove a redundant mutex unlock
Mao Wenan (1):
net: Update window_clamp if SOCK_RCVBUF is set
Marc Zyngier (2):
arm64: Run ARCH_WORKAROUND_1 enabling code on all CPUs
genirq/irqdomain: Don't try to free an interrupt that has no mapping
Mark Rutland (3):
arm64: syscall: exit userspace before unmasking exceptions
arm64: module: rework special section handling
arm64: module/ftrace: intialize PLT at load time
Martin Wilck (1):
scsi: core: Fix VPD LUN ID designator priorities
Mateusz Nosek (1):
futex: Fix incorrect should_fail_futex() handling
Matteo Croce (4):
Revert "kernel/reboot.c: convert simple_strtoul to kstrtoint"
reboot: fix overflow parsing reboot cpu number
ipv6: create multicast route with RTPROT_KERNEL
ipv6: set multicast flag on the multicast route
Matthew Wilcox (Oracle) (1):
mm/page_alloc.c: fix freeing non-compound pages
Maurizio Lombardi (2):
scsi: target: remove boilerplate code
scsi: target: fix hang when multiple threads try to destroy the same
iscsi session
Maxim Mikityanskiy (1):
net/tls: Protect from calling tls_dev_del for TLS RX twice
Miaohe Lin (1):
mm/hugetlb: fix potential missing huge page size info
Michael Schaller (1):
efivarfs: Replace invalid slashes with exclamation marks in dentries.
Mike Christie (1):
scsi: target: iscsi: Fix cmd abort fabric stop race
Mike Galbraith (1):
futex: Handle transient "ownerless" rtmutex state correctly
Miklos Szeredi (1):
fuse: fix page dereference after free
Mikulas Patocka (3):
dm integrity: fix the maximum number of arguments
dm integrity: fix flush with external metadata device
dm integrity: fix a crash if "recalculate" used without
"internal_hash"
Ming Lei (2):
scsi: core: Don't start concurrent async scan on same host
block: fix use-after-free in disk_part_iter_next
Minwoo Im (1):
nvme: free sq/cq dbbuf pointers when dbbuf set fails
Miroslav Benes (1):
module: set MODULE_STATE_GOING state when a module fails to load
Moshe Shemesh (2):
net/mlx4_en: Avoid scheduling restart task if it is already running
net/mlx4_en: Handle TX error CQE
Naoya Horiguchi (1):
mm, hwpoison: double-check page count in __get_any_page()
Naveen N. Rao (1):
ftrace: Fix updating FTRACE_FL_TRAMP
Neal Cardwell (1):
tcp: fix cwnd-limited bug for TSO deferral where we send nothing
NeilBrown (1):
NFS: switch nfsiod to be an UNBOUND workqueue.
Nicholas Piggin (1):
mm: fix exec activate_mm vs TLB shootdown and lazy tlb switching race
Oleg Nesterov (1):
ptrace: fix task_join_group_stop() for the case when current is traced
Oliver Herms (1):
IPv6: Set SIT tunnel hard_header_len to zero
Paul Moore (1):
selinux: fix inode_doinit_with_dentry() LABEL_INVALID error handling
Paulo Alcantara (1):
cifs: fix potential use-after-free in cifs_echo_request()
Peng Liu (1):
sched/deadline: Fix sched_dl_global_validate()
Peter Zijlstra (2):
serial: pl011: Fix lockdep splat when handling magic-sysrq interrupt
perf: Fix get_recursion_context()
Petr Malat (1):
sctp: Fix COMM_LOST/CANT_STR_ASSOC err reporting on big-endian
platforms
Qian Cai (1):
mm/swapfile: do not sleep with a spin lock held
Qiujun Huang (2):
ring-buffer: Return 0 on success from ring_buffer_resize()
tracing: Fix out of bounds write in get_trace_buf
Rafael J. Wysocki (1):
driver core: Extend device_is_dependent()
Randy Dunlap (1):
net: sched: prevent invalid Scell_log shift count
Ritika Srivastava (2):
block: Return blk_status_t instead of errno codes
block: better deal with the delayed not supported case in
blk_cloned_rq_check_limits
Ronnie Sahlberg (1):
cifs: handle -EINTR in cifs_setattr
Ryan Sharpelletti (1):
tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate
Sami Tolvanen (1):
arm64: lse: fix LSE atomics with LLVM's integrated assembler
Sean Tranchetti (1):
net: ipv6: fib: flush exceptions when purging route
Shakeel Butt (2):
mm: swap: fix vmstats for huge pages
mm: swap: memcg: fix memcg stats for huge pages
Shijie Luo (1):
mm: mempolicy: fix potential pte_unmap_unlock pte error
Shin'ichiro Kawasaki (1):
uio: Fix use-after-free in uio_unregister_device()
Stefano Brivio (1):
netfilter: ipset: Update byte and packet counters regardless of
whether they match
Steven Rostedt (VMware) (4):
ring-buffer: Fix recursion protection transitions between interrupt
context
ftrace: Fix recursion check for NMI test
ftrace: Handle tracing when switching between context
tracing: Fix userstacktrace option for instances
Subash Abhinov Kasiviswanathan (2):
netfilter: x_tables: Switch synchronization to RCU
netfilter: x_tables: Update remaining dereference to RCU
Sven Eckelmann (2):
vxlan: Add needed_headroom for lower device
vxlan: Copy needed_tailroom from lowerdev
Sylwester Dziedziuch (2):
i40e: Fix removing driver while bare-metal VFs pass traffic
i40e: Fix Error I40E_AQ_RC_EINVAL when removing VFs
Takashi Iwai (1):
libata: transport: Use scnprintf() for avoiding potential buffer
overflow
Tariq Toukan (1):
net: Disable NETIF_F_HW_TLS_RX when RXCSUM is disabled
Thomas Gleixner (12):
sched: Reenable interrupts in do_sched_yield()
futex: Move futex exit handling into futex code
futex: Replace PF_EXITPIDONE with a state
exit/exec: Seperate mm_release()
futex: Split futex_mm_release() for exit/exec
futex: Set task::futex_state to DEAD right after handling futex exit
futex: Mark the begin of futex exit explicitly
futex: Sanitize exit state handling
futex: Provide state handling for exec() as well
futex: Add mutex around futex exit
futex: Provide distinct return value when owner is exiting
futex: Prevent exit livelock
Tianyue Ren (1):
selinux: fix error initialization in inode_doinit_with_dentry()
Trond Myklebust (5):
SUNRPC: xprt_load_transport() needs to support the netid "rdma6"
NFSv4: Fix a pNFS layout related use-after-free race when freeing the
inode
pNFS: Mark layout for return if return-on-close was not sent
NFS/pNFS: Fix a leak of the layout 'plh_outstanding' counter
NFS: nfs_igrab_and_active must first reference the superblock
Tung Nguyen (1):
tipc: fix memory leak caused by tipc_buf_append()
Tyler Hicks (1):
tpm: efi: Don't create binary_bios_measurements file for an empty log
Uwe Kleine-König (1):
spi: fix resource leak for drivers without .remove callback
Vadim Fedorenko (1):
net/tls: missing received data after fast remote close
Valentin Schneider (1):
arm64: topology: Stop using MPIDR for topology information
Vamshi K Sthambamkadi (1):
efivarfs: fix memory leak in efivarfs_create()
Vasily Averin (2):
netfilter: ipset: fix shift-out-of-bounds in htable_bits()
net: drop bogus skb with CHECKSUM_PARTIAL and offset beyond end of
trimmed packet
Vincenzo Frascino (1):
arm64: lse: Fix LSE atomics with LLVM
Vladyslav Tarasiuk (1):
net/mlx5: Disable QoS when min_rates on all VFs are zero
Wang Hai (4):
devlink: Add missing genlmsg_cancel() in
devlink_nl_sb_port_pool_fill()
inet_diag: Fix error path to cancel the meseage in
inet_req_diag_fill()
tipc: fix memory leak in tipc_topsrv_start()
ipv6: addrlabel: fix possible memory leak in ip6addrlbl_net_init
Wang Wensheng (1):
sbsa_gwdt: Add WDIOF_PRETIMEOUT flag to watchdog_info at defination
Wei Li (1):
irqchip/gic-v3: Fix compiling error on ARM32 with GICv3
Wei Yang (1):
mm: thp: don't need care deferred split queue in memcg charge move
path
Weilong Chen (1):
hugetlbfs: Add dependency with ascend memory features
Wengang Wang (1):
ocfs2: initialize ip_next_orphan
Will Deacon (3):
arm64: psci: Avoid printing in cpu_psci_cpu_die()
arm64: pgtable: Fix pte_accessible()
arm64: pgtable: Ensure dirty bit is preserved across pte_wrprotect()
Willem de Bruijn (1):
sock: set sk_err to ee_errno on dequeue from errq
Wu Bo (1):
scsi: libiscsi: fix task hung when iscsid deamon exited
Xie XiuQi (1):
cputime: fix undefined reference to get_idle_time when CONFIG_PROC_FS
disabled
Xin Long (1):
sctp: change to hold/put transport for proto_unreach_timer
Xiongfeng Wang (1):
arm64: fix compile error when CONFIG_HOTPLUG_CPU is disabled
Xiubo Li (1):
nbd: make the config put is called before the notifying the waiter
Xu Qiang (4):
NMI: Enable arm-pmu interrupt as NMI in Acensed.
irqchip/gic-v3-its: Unconditionally save/restore the ITS state on
suspend.
irqchip/irq-gic-v3: Add workaround bindings in device tree to init ts
core GICR.
Document: In the binding document, add enable-init-all-GICR field
description.
Yang Shi (6):
mm: list_lru: set shrinker map bit when child nr_items is not zero
mm: thp: extract split_queue_* into a struct
mm: move mem_cgroup_uncharge out of __page_cache_release()
mm: shrinker: make shrinker not depend on memcg kmem
mm: thp: make deferred split shrinker memcg aware
mm: vmscan: protect shrinker idr replace with CONFIG_MEMCG
Yang Yingliang (5):
arm64: arch_timer: only do cntvct workaround on VDSO path on D05
armv7 fix compile error
Kconfig: disable KTASK by default
futex: sched: fix kabi broken in task_struct
futex: sched: fix UAF when free futex_exit_mutex in free_task()
Yi-Hung Wei (1):
ip_tunnels: Set tunnel option flag when tunnel metadata is present
Yicong Yang (1):
libfs: fix error cast of negative value in simple_attr_write()
Yu Kuai (2):
blk-cgroup: prevent rcu_sched detected stalls warnings in
blkg_destroy_all()
blk-throttle: don't check whether or not lower limit is valid if
CONFIG_BLK_DEV_THROTTLING_LOW is off
Yufen Yu (2):
bdi: fix compiler error in bdi_get_dev_name()
scsi: do quiesce for enclosure driver
Yunfeng Ye (1):
workqueue: Kick a worker based on the actual activation of delayed
works
Yunjian Wang (2):
net: hns: fix return value check in __lb_other_process()
vhost_net: fix ubuf refcount incorrectly when sendmsg fails
Yunsheng Lin (1):
net: sch_generic: fix the missing new qdisc assignment bug
Zeng Tao (1):
time: Prevent undefined behaviour in timespec64_to_ns()
Zhang Changzhong (2):
ah6: fix error return code in ah6_input()
net: bridge: vlan: fix error return code in __vlan_add()
Zhao Heming (2):
md/cluster: block reshape with remote resync job
md/cluster: fix deadlock when node is doing resync job
Zhengyuan Liu (3):
arm64/mm: return cpu_all_mask when node is NUMA_NO_NODE
hifc: remove unnecessary __init specifier
mmap: fix a compiling error for 'MAP_PA32BIT'
Zhou Guanghui (2):
memcg/ascend: Check sysctl oom config for memcg oom
memcg/ascend: enable kmem cgroup by default for ascend
Zqiang (1):
kthread_worker: prevent queuing delayed work from timer_fn when it is
being canceled
chenmaodong (1):
fix virtio_gpu use-after-free while creating dumb
j.nixdorf(a)avm.de (1):
net: sunrpc: interpret the return value of kstrtou32 correctly
lijinlin (1):
ext4: add ext3 report error to userspace by netlink
miaoyubo (1):
KVM: Enable PUD huge mappings only on 1620
yangerkun (1):
ext4: fix bug for rename with RENAME_WHITEOUT
zhuoliang zhang (1):
net: xfrm: fix a race condition during allocing spi
.../interrupt-controller/arm,gic-v3.txt | 4 +
Documentation/networking/bonding.txt | 16 +-
arch/Kconfig | 7 +
arch/alpha/include/uapi/asm/mman.h | 2 +
arch/arm/kernel/perf_event_v7.c | 16 +-
arch/arm64/Kconfig | 2 +
arch/arm64/configs/euleros_defconfig | 1 +
arch/arm64/configs/hulk_defconfig | 1 +
arch/arm64/configs/openeuler_defconfig | 3 +-
arch/arm64/include/asm/atomic_lse.h | 76 ++-
arch/arm64/include/asm/cpufeature.h | 4 +
arch/arm64/include/asm/lse.h | 6 +-
arch/arm64/include/asm/memory.h | 11 +
arch/arm64/include/asm/numa.h | 3 +
arch/arm64/include/asm/pgtable.h | 34 +-
arch/arm64/kernel/cpu_errata.c | 8 +
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/ftrace.c | 50 +-
arch/arm64/kernel/module.c | 47 +-
arch/arm64/kernel/psci.c | 5 +-
arch/arm64/kernel/setup.c | 5 +-
arch/arm64/kernel/syscall.c | 2 +-
arch/arm64/kernel/topology.c | 43 +-
arch/arm64/lib/memcpy.S | 3 +-
arch/arm64/lib/memmove.S | 3 +-
arch/arm64/lib/memset.S | 3 +-
arch/arm64/mm/init.c | 17 +-
arch/arm64/mm/numa.c | 6 +-
arch/mips/include/uapi/asm/mman.h | 2 +
arch/parisc/include/uapi/asm/mman.h | 2 +
arch/powerpc/include/asm/uaccess.h | 4 +-
arch/powerpc/include/uapi/asm/mman.h | 2 +
arch/sparc/include/uapi/asm/mman.h | 2 +
arch/x86/configs/hulk_defconfig | 1 +
arch/x86/configs/openeuler_defconfig | 1 +
arch/xtensa/include/uapi/asm/mman.h | 2 +
block/bfq-iosched.c | 8 +-
block/blk-cgroup.c | 30 +-
block/blk-core.c | 39 +-
block/blk-mq.c | 29 +-
block/blk-throttle.c | 6 +
block/genhd.c | 9 +-
drivers/acpi/acpi_pnp.c | 3 +
drivers/acpi/internal.h | 2 +-
drivers/acpi/numa.c | 2 +-
drivers/acpi/resource.c | 2 +-
drivers/acpi/scan.c | 17 +-
drivers/ata/libata-transport.c | 10 +-
drivers/base/core.c | 21 +-
drivers/block/nbd.c | 3 +-
drivers/block/null_blk_zoned.c | 20 +-
drivers/char/Kconfig | 2 +-
drivers/char/random.c | 1 -
drivers/char/tpm/eventlog/efi.c | 5 +
drivers/clocksource/arm_arch_timer.c | 36 +-
drivers/firmware/efi/efi.c | 4 -
drivers/firmware/efi/libstub/arm-stub.c | 3 -
drivers/gpu/drm/virtio/virtgpu_gem.c | 4 +-
drivers/irqchip/irq-gic-v3-its.c | 30 +-
drivers/irqchip/irq-gic-v3.c | 18 +-
drivers/md/dm-bufio.c | 6 +
drivers/md/dm-integrity.c | 58 ++-
drivers/md/dm-snap.c | 24 +
drivers/md/dm-table.c | 15 +-
drivers/md/dm-verity-target.c | 12 +-
drivers/md/md-cluster.c | 67 +--
drivers/md/md.c | 14 +-
drivers/mtd/hisilicon/sfc/hrd_sfc_driver.c | 4 +-
drivers/net/bonding/bond_main.c | 92 ++--
drivers/net/bonding/bond_netlink.c | 14 +
drivers/net/bonding/bond_options.c | 71 ++-
drivers/net/bonding/bond_procfs.c | 2 +
drivers/net/bonding/bond_sysfs.c | 13 +
drivers/net/bonding/bond_sysfs_slave.c | 18 +-
.../net/ethernet/hisilicon/hns/hns_ethtool.c | 4 +
drivers/net/ethernet/intel/i40e/i40e.h | 4 +
drivers/net/ethernet/intel/i40e/i40e_main.c | 32 +-
.../ethernet/intel/i40e/i40e_virtchnl_pf.c | 30 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 24 +-
.../net/ethernet/mellanox/mlx4/en_netdev.c | 21 +-
drivers/net/ethernet/mellanox/mlx4/en_tx.c | 40 +-
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 12 +-
.../net/ethernet/mellanox/mlx5/core/en_fs.c | 3 +
.../net/ethernet/mellanox/mlx5/core/eswitch.c | 15 +-
.../net/ethernet/mellanox/mlx5/core/main.c | 6 +-
.../ethernet/mellanox/mlx5/core/pagealloc.c | 21 +-
drivers/net/ethernet/mellanox/mlxsw/core.c | 8 +-
drivers/net/geneve.c | 3 +-
drivers/net/macvlan.c | 5 +-
drivers/net/virtio_net.c | 12 +-
drivers/net/vxlan.c | 3 +
drivers/nvme/host/pci.c | 15 +
drivers/pci/controller/pcie-iproc.c | 10 +-
drivers/pci/pci.c | 14 +-
drivers/pci/slot.c | 6 +-
drivers/scsi/huawei/hifc/unf_common.h | 2 +-
drivers/scsi/huawei/hifc/unf_scsi.c | 23 +
drivers/scsi/libiscsi.c | 33 +-
drivers/scsi/scsi_lib.c | 126 +++--
drivers/scsi/scsi_scan.c | 11 +-
drivers/scsi/scsi_transport_spi.c | 27 +-
drivers/spi/spi.c | 19 +-
drivers/target/iscsi/iscsi_target.c | 96 ++--
drivers/target/iscsi/iscsi_target.h | 1 -
drivers/target/iscsi/iscsi_target_configfs.c | 5 +-
drivers/target/iscsi/iscsi_target_login.c | 5 +-
drivers/tty/serial/amba-pl011.c | 11 +-
drivers/tty/serial/serial_core.c | 4 +
drivers/uio/uio.c | 12 +-
drivers/vfio/pci/vfio_pci.c | 3 +-
drivers/vhost/net.c | 6 +-
drivers/watchdog/sbsa_gwdt.c | 6 +-
fs/cifs/cifs_unicode.c | 8 +-
fs/cifs/connect.c | 2 +
fs/cifs/inode.c | 13 +-
fs/efivarfs/inode.c | 2 +
fs/efivarfs/super.c | 3 +
fs/exec.c | 17 +-
fs/ext4/ext4.h | 6 +-
fs/ext4/ext4_jbd2.c | 1 -
fs/ext4/file.c | 1 +
fs/ext4/inline.c | 1 +
fs/ext4/inode.c | 31 +-
fs/ext4/ioctl.c | 3 +
fs/ext4/mballoc.c | 1 +
fs/ext4/namei.c | 23 +-
fs/ext4/resize.c | 8 +-
fs/ext4/super.c | 32 +-
fs/ext4/xattr.c | 1 +
fs/fcntl.c | 10 +-
fs/filescontrol.c | 73 +--
fs/fuse/dev.c | 28 +-
fs/hugetlbfs/inode.c | 2 +-
fs/libfs.c | 6 +-
fs/lockd/host.c | 20 +-
fs/nfs/inode.c | 2 +-
fs/nfs/internal.h | 12 +-
fs/nfs/nfs4proc.c | 2 +-
fs/nfs/nfs4super.c | 2 +-
fs/nfs/pnfs.c | 40 +-
fs/nfs/pnfs.h | 5 +
fs/nfs_common/grace.c | 6 +-
fs/ocfs2/super.c | 1 +
fs/proc/generic.c | 55 ++-
fs/proc/internal.h | 7 +
fs/proc/proc_net.c | 16 -
fs/proc/self.c | 7 +
fs/quota/quota_tree.c | 8 +-
fs/super.c | 33 +-
fs/xfs/libxfs/xfs_alloc.c | 1 +
fs/xfs/libxfs/xfs_bmap.c | 19 +-
fs/xfs/libxfs/xfs_bmap.h | 2 +-
fs/xfs/libxfs/xfs_rmap.c | 2 +-
fs/xfs/scrub/bmap.c | 10 +-
fs/xfs/scrub/btree.c | 45 +-
fs/xfs/scrub/inode.c | 3 +-
fs/xfs/scrub/refcount.c | 8 +-
fs/xfs/xfs_iops.c | 10 +
fs/xfs/xfs_pnfs.c | 2 +-
fs/xfs/xfs_rtalloc.c | 10 +-
include/asm-generic/io.h | 39 +-
include/linux/backing-dev.h | 1 +
include/linux/blkdev.h | 1 +
include/linux/compat.h | 2 -
include/linux/dm-bufio.h | 1 +
include/linux/efi.h | 7 -
include/linux/futex.h | 39 +-
include/linux/huge_mm.h | 9 +
include/linux/hugetlb.h | 10 +-
include/linux/if_team.h | 5 +-
include/linux/memblock.h | 3 -
include/linux/memcontrol.h | 32 +-
include/linux/mm.h | 2 +
include/linux/mm_types.h | 1 +
include/linux/mman.h | 15 +
include/linux/mmzone.h | 8 +
include/linux/netfilter/x_tables.h | 5 +-
include/linux/netfilter_ipv4.h | 2 +-
include/linux/netfilter_ipv6.h | 2 +-
include/linux/netpoll.h | 10 +-
include/linux/prandom.h | 36 +-
include/linux/proc_fs.h | 8 +-
include/linux/sched.h | 5 +-
include/linux/sched/cputime.h | 5 +
include/linux/sched/mm.h | 6 +-
include/linux/shrinker.h | 7 +-
include/linux/skbuff.h | 5 +
include/linux/sunrpc/xprt.h | 1 +
include/linux/time64.h | 4 +
include/net/bond_options.h | 1 +
include/net/bonding.h | 14 +-
include/net/ip_tunnels.h | 7 +-
include/net/red.h | 4 +-
include/net/tls.h | 6 +
include/scsi/libiscsi.h | 3 +
include/target/iscsi/iscsi_target_core.h | 2 +-
include/uapi/asm-generic/mman.h | 1 +
include/uapi/linux/if_link.h | 1 +
init/Kconfig | 2 +-
kernel/events/internal.h | 2 +-
kernel/exit.c | 35 +-
kernel/fail_function.c | 5 +-
kernel/fork.c | 61 ++-
kernel/futex.c | 291 +++++++++--
kernel/irq/irqdomain.c | 11 +-
kernel/kthread.c | 3 +-
kernel/module.c | 6 +-
kernel/reboot.c | 28 +-
kernel/sched/core.c | 6 +-
kernel/sched/cputime.c | 6 +
kernel/sched/deadline.c | 5 +-
kernel/sched/sched.h | 42 +-
kernel/signal.c | 19 +-
kernel/time/itimer.c | 4 -
kernel/time/tick-common.c | 2 +
kernel/time/timer.c | 7 -
kernel/trace/ftrace.c | 22 +-
kernel/trace/ring_buffer.c | 66 ++-
kernel/trace/trace.c | 9 +-
kernel/trace/trace.h | 32 +-
kernel/trace/trace_selftest.c | 9 +-
kernel/workqueue.c | 13 +-
lib/Kconfig.debug | 9 +
lib/Makefile | 1 +
lib/fonts/font_10x18.c | 2 +-
lib/fonts/font_6x10.c | 2 +-
lib/fonts/font_6x11.c | 2 +-
lib/fonts/font_7x14.c | 2 +-
lib/fonts/font_8x16.c | 2 +-
lib/fonts/font_8x8.c | 2 +-
lib/fonts/font_acorn_8x8.c | 2 +-
lib/fonts/font_mini_4x6.c | 2 +-
lib/fonts/font_pearl_8x8.c | 2 +-
lib/fonts/font_sun12x22.c | 2 +-
lib/fonts/font_sun8x16.c | 2 +-
lib/genalloc.c | 25 +-
lib/random32.c | 462 +++++++++++-------
lib/scatterlist.c | 2 +-
lib/test_free_pages.c | 42 ++
mm/huge_memory.c | 167 +++++--
mm/hugetlb.c | 5 +-
mm/kasan/kasan_init.c | 23 +-
mm/list_lru.c | 10 +-
mm/memblock.c | 11 +-
mm/memcontrol.c | 34 +-
mm/memory-failure.c | 6 +
mm/mempolicy.c | 6 +-
mm/mlock.c | 25 +-
mm/mmap.c | 27 +-
mm/page_alloc.c | 9 +
mm/slub.c | 2 +-
mm/swap.c | 37 +-
mm/swapfile.c | 4 +-
mm/vmscan.c | 64 +--
net/8021q/vlan.c | 3 +-
net/8021q/vlan_dev.c | 5 +-
net/bridge/br_device.c | 1 +
net/bridge/br_netfilter_hooks.c | 7 +-
net/bridge/br_private.h | 5 +-
net/bridge/br_vlan.c | 4 +-
net/ceph/messenger.c | 5 +
net/core/dev.c | 5 +
net/core/devlink.c | 6 +-
net/core/lwt_bpf.c | 8 +-
net/core/net-sysfs.c | 65 ++-
net/core/netpoll.c | 51 +-
net/core/skbuff.c | 23 +-
net/dsa/slave.c | 5 +-
net/ipv4/fib_frontend.c | 2 +-
net/ipv4/gre_demux.c | 2 +-
net/ipv4/inet_diag.c | 4 +-
net/ipv4/ip_output.c | 2 +-
net/ipv4/ip_tunnel.c | 10 +-
net/ipv4/netfilter.c | 12 +-
net/ipv4/netfilter/arp_tables.c | 16 +-
net/ipv4/netfilter/ip_tables.c | 16 +-
net/ipv4/netfilter/ipt_SYNPROXY.c | 2 +-
net/ipv4/netfilter/ipt_rpfilter.c | 2 +-
net/ipv4/netfilter/iptable_mangle.c | 2 +-
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 2 +-
net/ipv4/netfilter/nf_reject_ipv4.c | 2 +-
net/ipv4/netfilter/nft_chain_route_ipv4.c | 2 +-
net/ipv4/route.c | 7 +-
net/ipv4/syncookies.c | 9 +-
net/ipv4/tcp.c | 2 +
net/ipv4/tcp_bbr.c | 2 +-
net/ipv4/tcp_cong.c | 5 +
net/ipv4/tcp_input.c | 6 +-
net/ipv4/tcp_output.c | 9 +-
net/ipv4/udp.c | 3 +-
net/ipv6/addrconf.c | 3 +-
net/ipv6/addrlabel.c | 26 +-
net/ipv6/ah6.c | 3 +-
net/ipv6/ip6_fib.c | 5 +-
net/ipv6/ip6_gre.c | 16 +-
net/ipv6/ip6_output.c | 40 +-
net/ipv6/netfilter.c | 6 +-
net/ipv6/netfilter/ip6_tables.c | 16 +-
net/ipv6/netfilter/ip6table_mangle.c | 2 +-
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | 2 +-
net/ipv6/netfilter/nft_chain_route_ipv6.c | 2 +-
net/ipv6/sit.c | 2 -
net/ipv6/syncookies.c | 10 +-
net/netfilter/ipset/ip_set_core.c | 3 +-
net/netfilter/ipset/ip_set_hash_gen.h | 20 +-
net/netfilter/ipvs/ip_vs_core.c | 4 +-
net/netfilter/nf_conntrack_standalone.c | 3 +
net/netfilter/nf_nat_core.c | 1 +
net/netfilter/nf_tables_api.c | 3 +-
net/netfilter/x_tables.c | 49 +-
net/netfilter/xt_RATEEST.c | 3 +
net/sched/cls_tcindex.c | 8 +-
net/sched/sch_api.c | 3 +-
net/sched/sch_choke.c | 2 +-
net/sched/sch_generic.c | 3 +
net/sched/sch_gred.c | 2 +-
net/sched/sch_netem.c | 9 +-
net/sched/sch_red.c | 2 +-
net/sched/sch_sfq.c | 2 +-
net/sctp/input.c | 4 +-
net/sctp/sm_sideeffect.c | 8 +-
net/sctp/transport.c | 2 +-
net/sunrpc/addr.c | 2 +-
net/sunrpc/xprt.c | 65 ++-
net/sunrpc/xprtrdma/module.c | 1 +
net/sunrpc/xprtrdma/transport.c | 1 +
net/sunrpc/xprtsock.c | 4 +
net/tipc/link.c | 9 +-
net/tipc/msg.c | 5 +-
net/tipc/topsrv.c | 10 +-
net/tls/tls_device.c | 5 +-
net/tls/tls_sw.c | 6 +
net/xdp/xsk.c | 8 +-
net/xfrm/xfrm_state.c | 8 +-
security/lsm_audit.c | 7 +-
security/selinux/hooks.c | 16 +-
security/selinux/ibpkey.c | 4 +-
sound/soc/codecs/Kconfig | 1 +
tools/include/uapi/linux/if_link.h | 1 +
tools/perf/builtin-lock.c | 2 +-
tools/perf/util/print_binary.c | 2 +-
.../scripting-engines/trace-event-python.c | 7 +-
tools/perf/util/session.c | 1 +
virt/kvm/arm/mmu.c | 7 +
344 files changed, 3424 insertions(+), 1701 deletions(-)
create mode 100644 lib/test_free_pages.c
--
2.25.1
1
316

[PATCH 001/316] blk-cgroup: prevent rcu_sched detected stalls warnings in blkg_destroy_all()
by Cheng Jian 22 Feb '21
by Cheng Jian 22 Feb '21
22 Feb '21
From: Yu Kuai <yukuai3(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 46357
CVE: NA
---------------------------
test procedures:
a. create 20000 cgroups, and echo "8:0 10000" to
blkio.throttle.write_bps_device
b. echo 1 > /sys/blocd/sda/device/delete
test result:
rcu: INFO: rcu_sched detected stalls on CPUs/tasks: [5/1143]
rcu: 0-...0: (0 ticks this GP) idle=0f2/1/0x4000000000000000 softirq=15507/15507 fq
rcu: (detected by 6, t=60012 jiffies, g=119977, q=27153)
NMI backtrace for cpu 0
CPU: 0 PID: 443 Comm: bash Not tainted 4.19.95-00061-g0bcc83b30eec #63
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-p4
RIP: 0010:blk_throtl_update_limit_valid.isra.0+0x116/0x2a0
Code: 01 00 00 e8 7c dd 74 ff 48 83 bb 78 01 00 00 00 0f 85 54 01 00 00 48 8d bb 88 01 1
RSP: 0018:ffff8881030bf9f0 EFLAGS: 00000046
RAX: 0000000000000000 RBX: ffff8880b4f37080 RCX: ffffffff95da0afe
RDX: dffffc0000000000 RSI: ffff888100373980 RDI: ffff8880b4f37208
RBP: ffff888100deca00 R08: ffffffff9528f951 R09: 0000000000000001
R10: ffffed10159dbf56 R11: ffff8880acedfab3 R12: ffff8880b9fda498
R13: ffff8880b9fda4f4 R14: 0000000000000050 R15: ffffffff98b622c0
FS: 00007feb51c51700(0000) GS:ffff888106200000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000561619547080 CR3: 0000000102bc9000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
throtl_pd_offline+0x98/0x100
blkg_destroy+0x133/0x630
? blkcg_deactivate_policy+0x2c0/0x2c0
? lock_timer_base+0x65/0x110
blkg_destroy_all+0x7f/0x100
blkcg_exit_queue+0x3f/0xa5
blk_exit_queue+0x69/0xa0
blk_cleanup_queue+0x226/0x360
__scsi_remove_device+0xb4/0x3c0
scsi_remove_device+0x38/0x60
sdev_store_delete+0x74/0x100
? dev_driver_string+0xb0/0xb0
dev_attr_store+0x41/0x70
sysfs_kf_write+0x89/0xc0
kernfs_fop_write+0x1b6/0x2e0
? sysfs_kf_bin_read+0x130/0x130
__vfs_write+0xca/0x420
? kernel_read+0xc0/0xc0
? __alloc_fd+0x16f/0x2d0
? __fd_install+0x95/0x1a0
? handle_mm_fault+0x3e0/0x560
vfs_write+0x11a/0x2f0
ksys_write+0xb9/0x1e0
? __x64_sys_read+0x60/0x60
? kasan_check_write+0x20/0x30
? filp_close+0xb5/0xf0
__x64_sys_write+0x46/0x60
do_syscall_64+0xd9/0x1f0
entry_SYSCALL_64_after_hwframe+0x44/0xa9
The usage of so many blkg is very rare, however, such problem do exist
in theory. In order to avoid such warnings, release 'q->queue_lock' for
a while when a batch of blkg were destroyed.
Signed-off-by: Yu Kuai <yukuai3(a)huawei.com>
Reviewed-by: Tao Hou <houtao1(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Cheng Jian <cj.chengjian(a)huawei.com>
---
block/blk-cgroup.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index e592167449aa..c64f0afa27dc 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -364,16 +364,31 @@ static void blkg_destroy(struct blkcg_gq *blkg)
*/
static void blkg_destroy_all(struct request_queue *q)
{
+#define BLKG_DESTROY_BATCH 4096
struct blkcg_gq *blkg, *n;
+ int count;
lockdep_assert_held(q->queue_lock);
+again:
+ count = BLKG_DESTROY_BATCH;
list_for_each_entry_safe(blkg, n, &q->blkg_list, q_node) {
struct blkcg *blkcg = blkg->blkcg;
spin_lock(&blkcg->lock);
blkg_destroy(blkg);
spin_unlock(&blkcg->lock);
+ /*
+ * If the list is too long, the loop can took a long time,
+ * thus relese the lock for a while when a batch of blkg
+ * were destroyed.
+ */
+ if (!--count) {
+ spin_unlock_irq(q->queue_lock);
+ cond_resched();
+ spin_lock_irq(q->queue_lock);
+ goto again;
+ }
}
q->root_blkg = NULL;
--
2.25.1
1
13

[PATCH 001/316] blk-cgroup: prevent rcu_sched detected stalls warnings in blkg_destroy_all()
by Cheng Jian 22 Feb '21
by Cheng Jian 22 Feb '21
22 Feb '21
From: Yu Kuai <yukuai3(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 46357
CVE: NA
---------------------------
test procedures:
a. create 20000 cgroups, and echo "8:0 10000" to
blkio.throttle.write_bps_device
b. echo 1 > /sys/blocd/sda/device/delete
test result:
rcu: INFO: rcu_sched detected stalls on CPUs/tasks: [5/1143]
rcu: 0-...0: (0 ticks this GP) idle=0f2/1/0x4000000000000000 softirq=15507/15507 fq
rcu: (detected by 6, t=60012 jiffies, g=119977, q=27153)
NMI backtrace for cpu 0
CPU: 0 PID: 443 Comm: bash Not tainted 4.19.95-00061-g0bcc83b30eec #63
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-p4
RIP: 0010:blk_throtl_update_limit_valid.isra.0+0x116/0x2a0
Code: 01 00 00 e8 7c dd 74 ff 48 83 bb 78 01 00 00 00 0f 85 54 01 00 00 48 8d bb 88 01 1
RSP: 0018:ffff8881030bf9f0 EFLAGS: 00000046
RAX: 0000000000000000 RBX: ffff8880b4f37080 RCX: ffffffff95da0afe
RDX: dffffc0000000000 RSI: ffff888100373980 RDI: ffff8880b4f37208
RBP: ffff888100deca00 R08: ffffffff9528f951 R09: 0000000000000001
R10: ffffed10159dbf56 R11: ffff8880acedfab3 R12: ffff8880b9fda498
R13: ffff8880b9fda4f4 R14: 0000000000000050 R15: ffffffff98b622c0
FS: 00007feb51c51700(0000) GS:ffff888106200000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000561619547080 CR3: 0000000102bc9000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
throtl_pd_offline+0x98/0x100
blkg_destroy+0x133/0x630
? blkcg_deactivate_policy+0x2c0/0x2c0
? lock_timer_base+0x65/0x110
blkg_destroy_all+0x7f/0x100
blkcg_exit_queue+0x3f/0xa5
blk_exit_queue+0x69/0xa0
blk_cleanup_queue+0x226/0x360
__scsi_remove_device+0xb4/0x3c0
scsi_remove_device+0x38/0x60
sdev_store_delete+0x74/0x100
? dev_driver_string+0xb0/0xb0
dev_attr_store+0x41/0x70
sysfs_kf_write+0x89/0xc0
kernfs_fop_write+0x1b6/0x2e0
? sysfs_kf_bin_read+0x130/0x130
__vfs_write+0xca/0x420
? kernel_read+0xc0/0xc0
? __alloc_fd+0x16f/0x2d0
? __fd_install+0x95/0x1a0
? handle_mm_fault+0x3e0/0x560
vfs_write+0x11a/0x2f0
ksys_write+0xb9/0x1e0
? __x64_sys_read+0x60/0x60
? kasan_check_write+0x20/0x30
? filp_close+0xb5/0xf0
__x64_sys_write+0x46/0x60
do_syscall_64+0xd9/0x1f0
entry_SYSCALL_64_after_hwframe+0x44/0xa9
The usage of so many blkg is very rare, however, such problem do exist
in theory. In order to avoid such warnings, release 'q->queue_lock' for
a while when a batch of blkg were destroyed.
Signed-off-by: Yu Kuai <yukuai3(a)huawei.com>
Reviewed-by: Tao Hou <houtao1(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Cheng Jian <cj.chengjian(a)huawei.com>
---
block/blk-cgroup.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index e592167449aa..c64f0afa27dc 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -364,16 +364,31 @@ static void blkg_destroy(struct blkcg_gq *blkg)
*/
static void blkg_destroy_all(struct request_queue *q)
{
+#define BLKG_DESTROY_BATCH 4096
struct blkcg_gq *blkg, *n;
+ int count;
lockdep_assert_held(q->queue_lock);
+again:
+ count = BLKG_DESTROY_BATCH;
list_for_each_entry_safe(blkg, n, &q->blkg_list, q_node) {
struct blkcg *blkcg = blkg->blkcg;
spin_lock(&blkcg->lock);
blkg_destroy(blkg);
spin_unlock(&blkcg->lock);
+ /*
+ * If the list is too long, the loop can took a long time,
+ * thus relese the lock for a while when a batch of blkg
+ * were destroyed.
+ */
+ if (!--count) {
+ spin_unlock_irq(q->queue_lock);
+ cond_resched();
+ spin_lock_irq(q->queue_lock);
+ goto again;
+ }
}
q->root_blkg = NULL;
--
2.25.1
1
4
2
1
申报议题:
2. 讨论设立sig安全联络员及如何缩短sig所属项目的CVE响应时间
魏刚
---Original---
From: "openEuler conference"<public(a)openeuler.io>
Date: Thu, Feb 18, 2021 17:12 PM
To: "dev"<dev(a)openeuler.org>;"kernel"<kernel(a)openeuler.org>;
Subject: [Dev] openEuler kernel sig meeting
您好!
openEuler Kernel SIG 邀请您参加 2021-02-19 10:00 召开的ZOOM会议
会议主题:openEuler kernel sig meeting
会议内容:1. 树莓派补丁合入openEuler 5.10 内核讨论
会议链接:https://zoom.us/j/92887086207?pwd=emdmSVVFekh5eXRSczNNTngrcWYzUT09
更多资讯尽在:https://openeuler.org/zh/
Hello!
openEuler Kernel SIG invites you to attend the ZOOM conference will be held at 2021-02-19 10:00,
The subject of the conference is openEuler kernel sig meeting,
Summary: 1. 树莓派补丁合入openEuler 5.10 内核讨论
You can join the meeting at https://zoom.us/j/92887086207?pwd=emdmSVVFekh5eXRSczNNTngrcWYzUT09.
More information
1
0
Arnold Gozum (1):
platform/x86: intel-vbtn: Support for tablet mode on Dell Inspiron
7352
Brian King (1):
scsi: ibmvfc: Set default timeout to avoid crash during migration
Christian Brauner (1):
sysctl: handle overflow in proc_get_long
Eric Dumazet (1):
net_sched: gen_estimator: support large ewma log
Felix Fietkau (1):
mac80211: fix fast-rx encryption check
Greg Kroah-Hartman (1):
Linux 4.19.174
Hans de Goede (1):
platform/x86: touchscreen_dmi: Add swap-x-y quirk for Goodix
touchscreen on Estar Beauty HD tablet
Javed Hasan (1):
scsi: libfc: Avoid invoking response handler twice if ep is already
completed
Josh Poimboeuf (1):
objtool: Don't fail on missing symbol table
Lijun Pan (1):
ibmvnic: Ensure that CRQ entry read are correctly ordered
Martin Wilck (1):
scsi: scsi_transport_srp: Don't block target in failfast state
Michael Ellerman (1):
selftests/powerpc: Only test lwm/stmw on big endian
Pan Bian (1):
net: dsa: bcm_sf2: put device node before return
Peter Zijlstra (3):
x86: __always_inline __{rd,wr}msr()
kthread: Extract KTHREAD_IS_PER_CPU
workqueue: Restrict affinity change to rescuer
Rafael J. Wysocki (1):
ACPI: thermal: Do not call acpi_thermal_check() directly
Tony Lindgren (1):
phy: cpcap-usb: Fix warning for missing regulator_disable
Makefile | 2 +-
arch/x86/include/asm/msr.h | 4 +-
drivers/acpi/thermal.c | 55 +++++++++++++------
drivers/net/dsa/bcm_sf2.c | 8 ++-
drivers/net/ethernet/ibm/ibmvnic.c | 6 ++
drivers/phy/motorola/phy-cpcap-usb.c | 19 +++++--
drivers/platform/x86/intel-vbtn.c | 6 ++
drivers/platform/x86/touchscreen_dmi.c | 18 ++++++
drivers/scsi/ibmvscsi/ibmvfc.c | 4 +-
drivers/scsi/libfc/fc_exch.c | 16 +++++-
drivers/scsi/scsi_transport_srp.c | 9 ++-
include/linux/kthread.h | 3 +
kernel/kthread.c | 27 ++++++++-
kernel/smpboot.c | 1 +
kernel/sysctl.c | 2 +
kernel/workqueue.c | 9 +--
net/core/gen_estimator.c | 11 ++--
net/mac80211/rx.c | 2 +
tools/objtool/elf.c | 7 ++-
.../powerpc/alignment/alignment_handler.c | 5 +-
20 files changed, 168 insertions(+), 46 deletions(-)
--
2.25.1
1
18

[PATCH kernel-4.19 1/3] mmap: fix a compiling error for 'MAP_CHECKNODE'
by Yang Yingliang 09 Feb '21
by Yang Yingliang 09 Feb '21
09 Feb '21
From: Bixuan Cui <cuibixuan(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA
MAP_CHECKNODE was defined in uapi/asm-generic/mman.h, that was not
automatically included by mm/mmap.c when building on platforms such as
mips, and result in following compiling error:
mm/mmap.c: In function ‘__do_mmap’:
mm/mmap.c:1581:14: error: ‘MAP_CHECKNODE’ undeclared (first use in this function)
if (flags & MAP_CHECKNODE)
^
mm/mmap.c:1581:14: note: each undeclared identifier is reported only once for each function it appears in
scripts/Makefile.build:303: recipe for target 'mm/mmap.o' failed
Fixes: 56a22a261008 ("arm64/ascend: mm: Add MAP_CHECKNODE flag to check node hugetlb")
Signed-off-by: Bixuan Cui <cuibixuan(a)huawei.com>
Reviewed-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
arch/alpha/include/uapi/asm/mman.h | 1 +
arch/mips/include/uapi/asm/mman.h | 1 +
arch/parisc/include/uapi/asm/mman.h | 1 +
arch/powerpc/include/uapi/asm/mman.h | 1 +
arch/sparc/include/uapi/asm/mman.h | 1 +
arch/xtensa/include/uapi/asm/mman.h | 1 +
6 files changed, 6 insertions(+)
diff --git a/arch/alpha/include/uapi/asm/mman.h b/arch/alpha/include/uapi/asm/mman.h
index b3acfc00c8ec5..1c7ce2716ad37 100644
--- a/arch/alpha/include/uapi/asm/mman.h
+++ b/arch/alpha/include/uapi/asm/mman.h
@@ -34,6 +34,7 @@
#define MAP_HUGETLB 0x100000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x200000/* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#define MS_ASYNC 1 /* sync memory asynchronously */
#define MS_SYNC 2 /* synchronous memory sync */
diff --git a/arch/mips/include/uapi/asm/mman.h b/arch/mips/include/uapi/asm/mman.h
index 72a00c746e781..4570a54ac1d90 100644
--- a/arch/mips/include/uapi/asm/mman.h
+++ b/arch/mips/include/uapi/asm/mman.h
@@ -52,6 +52,7 @@
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
/*
* Flags for msync
diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h
index 9e989d649e854..06857eb1bee8f 100644
--- a/arch/parisc/include/uapi/asm/mman.h
+++ b/arch/parisc/include/uapi/asm/mman.h
@@ -28,6 +28,7 @@
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#define MS_SYNC 1 /* synchronous memory sync */
#define MS_ASYNC 2 /* sync memory asynchronously */
diff --git a/arch/powerpc/include/uapi/asm/mman.h b/arch/powerpc/include/uapi/asm/mman.h
index 95f884ada96f1..24354f792b00d 100644
--- a/arch/powerpc/include/uapi/asm/mman.h
+++ b/arch/powerpc/include/uapi/asm/mman.h
@@ -30,6 +30,7 @@
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
/* Override any generic PKEY permission defines */
#define PKEY_DISABLE_EXECUTE 0x4
diff --git a/arch/sparc/include/uapi/asm/mman.h b/arch/sparc/include/uapi/asm/mman.h
index 0d1881b8f30d1..214abe17f44a0 100644
--- a/arch/sparc/include/uapi/asm/mman.h
+++ b/arch/sparc/include/uapi/asm/mman.h
@@ -27,6 +27,7 @@
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#endif /* _UAPI__SPARC_MMAN_H__ */
diff --git a/arch/xtensa/include/uapi/asm/mman.h b/arch/xtensa/include/uapi/asm/mman.h
index f584a590bb001..2c9d705602382 100644
--- a/arch/xtensa/include/uapi/asm/mman.h
+++ b/arch/xtensa/include/uapi/asm/mman.h
@@ -59,6 +59,7 @@
#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
#define MAP_PA32BIT 0x400000 /* physical address is within 4G */
+#define MAP_CHECKNODE 0x800000 /* hugetlb numa node check */
#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
# define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be
* uninitialized */
--
2.25.1
1
2