From: Lijun Fang fanglijun3@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4JMM0 CVE: NA
--------
Add svm_get_phy_memory_info and svm_get_hugeinfo to get meminfo.
Signed-off-by: Lijun Fang fanglijun3@huawei.com Reviewed-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/char/svm.c | 118 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/char/svm.c b/drivers/char/svm.c index bf9e299ceb4e..79b7e8f9b803 100644 --- a/drivers/char/svm.c +++ b/drivers/char/svm.c @@ -37,6 +37,8 @@ #define ASID_SHIFT 48
#define SVM_IOCTL_REMAP_PROC 0xfff4 +#define SVM_IOCTL_GETHUGEINFO 0xfff6 +#define SVM_IOCTL_GET_PHYMEMINFO 0xfff8 #define SVM_IOCTL_LOAD_FLAG 0xfffa #define SVM_IOCTL_PROCESS_BIND 0xffff
@@ -106,11 +108,32 @@ struct svm_proc_mem { u64 buf; };
+struct meminfo { + unsigned long hugetlbfree; + unsigned long hugetlbtotal; +}; + +struct phymeminfo { + unsigned long normal_total; + unsigned long normal_free; + unsigned long huge_total; + unsigned long huge_free; +}; + +struct phymeminfo_ioctl { + struct phymeminfo *info; + unsigned long nodemask; +}; + static char *svm_cmd_to_string(unsigned int cmd) { switch (cmd) { case SVM_IOCTL_PROCESS_BIND: return "bind"; + case SVM_IOCTL_GETHUGEINFO: + return "get hugeinfo"; + case SVM_IOCTL_GET_PHYMEMINFO: + return "get physical memory info"; case SVM_IOCTL_REMAP_PROC: return "remap proc"; case SVM_IOCTL_LOAD_FLAG: @@ -509,6 +532,95 @@ static int svm_open(struct inode *inode, struct file *file) return 0; }
+static long svm_get_hugeinfo(unsigned long __user *arg) +{ + struct hstate *h = &default_hstate; + struct meminfo info; + + if (!acpi_disabled) + return -EPERM; + + if (arg == NULL) + return -EINVAL; + + if (!hugepages_supported()) + return -ENOTSUPP; + + info.hugetlbfree = h->free_huge_pages; + info.hugetlbtotal = h->nr_huge_pages; + + if (copy_to_user((void __user *)arg, &info, sizeof(info))) + return -EFAULT; + + pr_info("svm get hugetlb info: order(%u), max_huge_pages(%lu)," + "nr_huge_pages(%lu), free_huge_pages(%lu), resv_huge_pages(%lu)", + h->order, + h->max_huge_pages, + h->nr_huge_pages, + h->free_huge_pages, + h->resv_huge_pages); + + return 0; +} + +static void svm_get_node_memory_info_inc(unsigned long nid, struct phymeminfo *info) +{ + struct sysinfo i; + struct hstate *h = &default_hstate; + unsigned long huge_free = 0; + unsigned long huge_total = 0; + + if (hugepages_supported()) { + huge_free = h->free_huge_pages_node[nid] * (PAGE_SIZE << huge_page_order(h)); + huge_total = h->nr_huge_pages_node[nid] * (PAGE_SIZE << huge_page_order(h)); + } + +#ifdef CONFIG_NUMA + si_meminfo_node(&i, nid); +#else + si_meminfo(&i); +#endif + info->normal_free += i.freeram * PAGE_SIZE; + info->normal_total += i.totalram * PAGE_SIZE - huge_total; + info->huge_total += huge_total; + info->huge_free += huge_free; +} + +static void __svm_get_memory_info(unsigned long nodemask, struct phymeminfo *info) +{ + memset(info, 0x0, sizeof(struct phymeminfo)); + + nodemask = nodemask & ((1UL << MAX_NUMNODES) - 1); + + while (nodemask) { + unsigned long nid = find_first_bit(&nodemask, BITS_PER_LONG); + + if (node_isset(nid, node_online_map)) + (void)svm_get_node_memory_info_inc(nid, info); + + nodemask &= ~(1UL << nid); + } +} + +static long svm_get_phy_memory_info(unsigned long __user *arg) +{ + struct phymeminfo info; + struct phymeminfo_ioctl para; + + if (arg == NULL) + return -EINVAL; + + if (copy_from_user(¶, (void __user *)arg, sizeof(para))) + return -EFAULT; + + __svm_get_memory_info(para.nodemask, &info); + + if (copy_to_user((void __user *)para.info, &info, sizeof(info))) + return -EFAULT; + + return 0; +} + static long svm_remap_get_phys(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long *phys, unsigned long *page_size, unsigned long *offset) @@ -868,6 +980,12 @@ static long svm_ioctl(struct file *file, unsigned int cmd, return -EFAULT; } break; + case SVM_IOCTL_GETHUGEINFO: + err = svm_get_hugeinfo((unsigned long __user *)arg); + break; + case SVM_IOCTL_GET_PHYMEMINFO: + err = svm_get_phy_memory_info((unsigned long __user *)arg); + break; case SVM_IOCTL_REMAP_PROC: err = svm_remap_proc((unsigned long __user *)arg); break;