clear-pkgs-linux-iot-lts2018/0938-ACRNTrace-Refine-acrn-...

325 lines
8.5 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kaige Fu <kaige.fu@intel.com>
Date: Thu, 13 Dec 2018 11:15:37 +0000
Subject: [PATCH] ACRNTrace: Refine acrn trace module to remove the limitation
on fixed CPU number hardcode
Currently acrn_trace works in static allocation mode and it only works
on the fixed CPU number. If one new platform with more CPU cores, it fails
to work.
This patch tries to refine the acrn trace module so that it can work on
the queried CPU number.
Change-Id: I4e62ec5f41bf4fd48d8a5d626c9736504b24c689
Tracked-On: projectacrn/acrn-hypervisor#1775
Signed-off-by: Kaige Fu <kaige.fu@intel.com>
Reviewed-by: Zhao Yakui <yakui.zhao@intel.com>
Tracked-On: PKT-1696
---
drivers/acrn/acrn_trace.c | 177 +++++++++++++++++---------------------
1 file changed, 79 insertions(+), 98 deletions(-)
diff --git a/drivers/acrn/acrn_trace.c b/drivers/acrn/acrn_trace.c
index d48b03625223..852c8b0323a5 100644
--- a/drivers/acrn/acrn_trace.c
+++ b/drivers/acrn/acrn_trace.c
@@ -59,9 +59,12 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/major.h>
+#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/mm.h>
+#include <linux/vhm/vhm_hypercall.h>
+#include <linux/vhm/acrn_hv_defs.h>
#include <asm/hypervisor.h>
@@ -76,38 +79,19 @@
#define foreach_cpu(cpu, cpu_num) \
for ((cpu) = 0; (cpu) < (cpu_num); (cpu)++)
-#define MAX_NR_CPUS 4
+#define DEFAULT_NR_CPUS 4
/* actual physical cpu number, initialized by module init */
-static int pcpu_num;
-
-static int nr_cpus = MAX_NR_CPUS;
-module_param(nr_cpus, int, S_IRUSR | S_IWUSR);
-
-static atomic_t open_cnt[MAX_NR_CPUS];
-static shared_buf_t *sbuf_per_cpu[MAX_NR_CPUS];
-
-static inline int get_id_from_devname(struct file *filep)
-{
- uint32_t cpuid;
- int err;
- char id_str[16];
- struct miscdevice *dev = filep->private_data;
-
- strncpy(id_str, (void *)dev->name + sizeof("acrn_trace_") - 1, 16);
- id_str[15] = '\0';
- err = kstrtoul(&id_str[0], 10, (unsigned long *)&cpuid);
-
- if (err)
- return err;
-
- if (cpuid >= pcpu_num) {
- pr_err("%s, failed to get cpuid, cpuid %d\n",
- __func__, cpuid);
- return -1;
- }
+static int pcpu_num = DEFAULT_NR_CPUS;
+
+struct acrn_trace {
+ struct miscdevice miscdev;
+ char name[24];
+ shared_buf_t *sbuf;
+ atomic_t open_cnt;
+ uint16_t pcpu_id;
+};
- return cpuid;
-}
+static struct acrn_trace *acrn_trace_devs;
/************************************************************************
*
@@ -116,51 +100,62 @@ static inline int get_id_from_devname(struct file *filep)
***********************************************************************/
static int acrn_trace_open(struct inode *inode, struct file *filep)
{
- int cpuid = get_id_from_devname(filep);
+ struct acrn_trace *dev;
- pr_debug("%s, cpu %d\n", __func__, cpuid);
- if (cpuid < 0)
- return -ENXIO;
+ dev = container_of(filep->private_data, struct acrn_trace, miscdev);
+ if (!dev) {
+ pr_err("No such dev\n");
+ return -ENODEV;
+ }
+ pr_debug("%s, cpu %d\n", __func__, dev->pcpu_id);
/* More than one reader at the same time could get data messed up */
- if (atomic_read(&open_cnt[cpuid]))
+ if (atomic_read(&dev->open_cnt))
return -EBUSY;
- atomic_inc(&open_cnt[cpuid]);
+ atomic_inc(&dev->open_cnt);
return 0;
}
static int acrn_trace_release(struct inode *inode, struct file *filep)
{
- int cpuid = get_id_from_devname(filep);
+ struct acrn_trace *dev;
+
+ dev = container_of(filep->private_data, struct acrn_trace, miscdev);
+ if (!dev) {
+ pr_err("No such dev\n");
+ return -ENODEV;
+ }
- pr_debug("%s, cpu %d\n", __func__, cpuid);
- if (cpuid < 0)
- return -ENXIO;
+ pr_debug("%s, cpu %d\n", __func__, dev->pcpu_id);
- atomic_dec(&open_cnt[cpuid]);
+ atomic_dec(&dev->open_cnt);
return 0;
}
static int acrn_trace_mmap(struct file *filep, struct vm_area_struct *vma)
{
- int cpuid = get_id_from_devname(filep);
phys_addr_t paddr;
+ struct acrn_trace *dev;
- pr_debug("%s, cpu %d\n", __func__, cpuid);
- if (cpuid < 0)
- return -ENXIO;
+ dev = container_of(filep->private_data, struct acrn_trace, miscdev);
+ if (!dev) {
+ pr_err("No such dev\n");
+ return -ENODEV;
+ }
- BUG_ON(!virt_addr_valid(sbuf_per_cpu[cpuid]));
- paddr = virt_to_phys(sbuf_per_cpu[cpuid]);
+ pr_debug("%s, cpu %d\n", __func__, dev->pcpu_id);
+
+ WARN_ON(!virt_addr_valid(dev->sbuf));
+ paddr = virt_to_phys(dev->sbuf);
if (remap_pfn_range(vma, vma->vm_start,
paddr >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot)) {
- pr_err("Failed to mmap sbuf for cpu%d\n", cpuid);
+ pr_err("Failed to mmap sbuf for cpu%d\n", dev->pcpu_id);
return -EAGAIN;
}
@@ -174,37 +169,6 @@ static const struct file_operations acrn_trace_fops = {
.mmap = acrn_trace_mmap,
};
-static struct miscdevice acrn_trace_dev0 = {
- .name = "acrn_trace_0",
- .minor = MISC_DYNAMIC_MINOR,
- .fops = &acrn_trace_fops,
-};
-
-static struct miscdevice acrn_trace_dev1 = {
- .name = "acrn_trace_1",
- .minor = MISC_DYNAMIC_MINOR,
- .fops = &acrn_trace_fops,
-};
-
-static struct miscdevice acrn_trace_dev2 = {
- .name = "acrn_trace_2",
- .minor = MISC_DYNAMIC_MINOR,
- .fops = &acrn_trace_fops,
-};
-
-static struct miscdevice acrn_trace_dev3 = {
- .name = "acrn_trace_3",
- .minor = MISC_DYNAMIC_MINOR,
- .fops = &acrn_trace_fops,
-};
-
-static struct miscdevice *acrn_trace_devs[4] = {
- &acrn_trace_dev0,
- &acrn_trace_dev1,
- &acrn_trace_dev2,
- &acrn_trace_dev3,
-};
-
/*
* acrn_trace_init()
*/
@@ -212,34 +176,37 @@ static int __init acrn_trace_init(void)
{
int ret = 0;
int i, cpu;
+ shared_buf_t *sbuf;
+ struct miscdevice *miscdev;
+ struct acrn_hw_info hw_info;
if (x86_hyper_type != X86_HYPER_ACRN) {
pr_err("acrn_trace: not support acrn hypervisor!\n");
return -EINVAL;
}
- /* TBD: we could get the native cpu number by hypercall later */
- pr_info("%s, cpu_num %d\n", __func__, nr_cpus);
- if (nr_cpus > MAX_NR_CPUS) {
- pr_err("nr_cpus %d exceed MAX_NR_CPUS %d !\n",
- nr_cpus, MAX_NR_CPUS);
- return -EINVAL;
- }
- pcpu_num = nr_cpus;
+ ret = hcall_get_hw_info(virt_to_phys(&hw_info));
+ if (!ret)
+ pcpu_num = hw_info.cpu_num;
+
+ acrn_trace_devs = kcalloc(pcpu_num, sizeof(struct acrn_trace),
+ GFP_KERNEL);
+ if (!acrn_trace_devs)
+ return -ENOMEM;
foreach_cpu(cpu, pcpu_num) {
/* allocate shared_buf */
- sbuf_per_cpu[cpu] = sbuf_allocate(TRACE_ELEMENT_NUM,
- TRACE_ELEMENT_SIZE);
- if (!sbuf_per_cpu[cpu]) {
- pr_err("Failed alloc SBuf, cpuid %d\n", cpu);
+ sbuf = sbuf_allocate(TRACE_ELEMENT_NUM, TRACE_ELEMENT_SIZE);
+ if (!sbuf) {
ret = -ENOMEM;
goto out_free;
}
+ acrn_trace_devs[cpu].sbuf = sbuf;
}
foreach_cpu(cpu, pcpu_num) {
- ret = sbuf_share_setup(cpu, ACRN_TRACE, sbuf_per_cpu[cpu]);
+ sbuf = acrn_trace_devs[cpu].sbuf;
+ ret = sbuf_share_setup(cpu, ACRN_TRACE, sbuf);
if (ret < 0) {
pr_err("Failed to setup SBuf, cpuid %d\n", cpu);
goto out_sbuf;
@@ -247,7 +214,17 @@ static int __init acrn_trace_init(void)
}
foreach_cpu(cpu, pcpu_num) {
- ret = misc_register(acrn_trace_devs[cpu]);
+ acrn_trace_devs[cpu].pcpu_id = cpu;
+
+ miscdev = &acrn_trace_devs[cpu].miscdev;
+ snprintf(acrn_trace_devs[cpu].name,
+ sizeof(acrn_trace_devs[cpu].name),
+ "acrn_trace_%d", cpu);
+ miscdev->name = acrn_trace_devs[cpu].name;
+ miscdev->minor = MISC_DYNAMIC_MINOR;
+ miscdev->fops = &acrn_trace_fops;
+
+ ret = misc_register(&acrn_trace_devs[cpu].miscdev);
if (ret < 0) {
pr_err("Failed to register acrn_trace_%d, errno %d\n",
cpu, ret);
@@ -255,11 +232,12 @@ static int __init acrn_trace_init(void)
}
}
+ pr_info("Initialized acrn trace module with %u cpu\n", pcpu_num);
return ret;
out_dereg:
for (i = --cpu; i >= 0; i--)
- misc_deregister(acrn_trace_devs[i]);
+ misc_deregister(&acrn_trace_devs[i].miscdev);
cpu = pcpu_num;
out_sbuf:
@@ -269,7 +247,8 @@ static int __init acrn_trace_init(void)
out_free:
for (i = --cpu; i >= 0; i--)
- sbuf_free(sbuf_per_cpu[i]);
+ sbuf_free(acrn_trace_devs[i].sbuf);
+ kfree(acrn_trace_devs);
return ret;
}
@@ -285,14 +264,16 @@ static void __exit acrn_trace_exit(void)
foreach_cpu(cpu, pcpu_num) {
/* deregister devices */
- misc_deregister(acrn_trace_devs[cpu]);
+ misc_deregister(&acrn_trace_devs[cpu].miscdev);
/* set sbuf pointer to NULL in HV */
sbuf_share_setup(cpu, ACRN_TRACE, NULL);
- /* free sbuf, sbuf_per_cpu[cpu] should be set NULL */
- sbuf_free(sbuf_per_cpu[cpu]);
+ /* free sbuf, per-cpu sbuf should be set NULL */
+ sbuf_free(acrn_trace_devs[cpu].sbuf);
}
+
+ kfree(acrn_trace_devs);
}
module_init(acrn_trace_init);
--
https://clearlinux.org