From: Yi-De Wu <yi-de.wu@mediatek.com>
To: Yingshiuan Pan <yingshiuan.pan@mediatek.com>,
Ze-Yu Wang <ze-yu.wang@mediatek.com>,
Yi-De Wu <yi-de.wu@mediatek.com>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Conor Dooley <conor+dt@kernel.org>,
Jonathan Corbet <corbet@lwn.net>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Richard Cochran <richardcochran@gmail.com>,
Matthias Brugger <matthias.bgg@gmail.com>,
AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com>
Cc: <devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<linux-doc@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>, <netdev@vger.kernel.org>,
<linux-mediatek@lists.infradead.org>,
David Bradil <dbrazdil@google.com>,
Trilok Soni <quic_tsoni@quicinc.com>,
My Chuang <my.chuang@mediatek.com>,
Shawn Hsiao <shawn.hsiao@mediatek.com>,
PeiLun Suei <peilun.suei@mediatek.com>,
Liju Chen <liju-clr.chen@mediatek.com>,
Willix Yeh <chi-shen.yeh@mediatek.com>,
Kevenny Hsieh <kevenny.hsieh@mediatek.com>
Subject: [PATCH v9 19/21] virt: geniezone: Provide individual VM memory statistics within debugfs
Date: Mon, 29 Jan 2024 16:33:00 +0800 [thread overview]
Message-ID: <20240129083302.26044-20-yi-de.wu@mediatek.com> (raw)
In-Reply-To: <20240129083302.26044-1-yi-de.wu@mediatek.com>
From: "Jerry Wang" <ze-yu.wang@mediatek.com>
Created a dedicated per-VM debugfs folder under gzvm, providing
user-level programs with easy access to per-VM memory statistics for
debugging and profiling purposes. This enables users to effectively
analyze and optimize the memory usage of individual virtual machines.
Two types of information can be obtained:
`cat /sys/kernel/debug/gzvm/<pid>-<vmid>/protected_hyp_mem` shows memory
used by the hypervisor and the size of the stage 2 table in bytes.
`cat /sys/kernel/debug/gzvm/<pid>-<vmid>/protected_shared_mem` gives
memory used by the shared resources of the guest and host in bytes.
For example:
console:/ # cat /sys/kernel/debug/gzvm/3417-15/protected_hyp_mem
180328
console:/ # cat /sys/kernel/debug/gzvm/3417-15/protected_shared_mem
262144
console:/ #
More stats will be added in the future.
Signed-off-by: Jerry Wang <ze-yu.wang@mediatek.com>
Signed-off-by: Liju-Clr Chen <liju-clr.chen@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
arch/arm64/geniezone/gzvm_arch_common.h | 2 +
arch/arm64/geniezone/vm.c | 13 +++
drivers/virt/geniezone/gzvm_main.c | 6 ++
drivers/virt/geniezone/gzvm_vm.c | 137 ++++++++++++++++++++++++
include/linux/gzvm_drv.h | 15 +++
5 files changed, 173 insertions(+)
diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h
index 07c5e2df7a74..fbaf2da792a4 100644
--- a/arch/arm64/geniezone/gzvm_arch_common.h
+++ b/arch/arm64/geniezone/gzvm_arch_common.h
@@ -26,6 +26,7 @@ enum {
GZVM_FUNC_SET_DTB_CONFIG = 16,
GZVM_FUNC_MAP_GUEST = 17,
GZVM_FUNC_MAP_GUEST_BLOCK = 18,
+ GZVM_FUNC_GET_STATISTICS = 19,
NR_GZVM_FUNC,
};
@@ -52,6 +53,7 @@ enum {
#define MT_HVC_GZVM_SET_DTB_CONFIG GZVM_HCALL_ID(GZVM_FUNC_SET_DTB_CONFIG)
#define MT_HVC_GZVM_MAP_GUEST GZVM_HCALL_ID(GZVM_FUNC_MAP_GUEST)
#define MT_HVC_GZVM_MAP_GUEST_BLOCK GZVM_HCALL_ID(GZVM_FUNC_MAP_GUEST_BLOCK)
+#define MT_HVC_GZVM_GET_STATISTICS GZVM_HCALL_ID(GZVM_FUNC_GET_STATISTICS)
#define GIC_V3_NR_LRS 16
diff --git a/arch/arm64/geniezone/vm.c b/arch/arm64/geniezone/vm.c
index 691e6521cc48..571326e70d98 100644
--- a/arch/arm64/geniezone/vm.c
+++ b/arch/arm64/geniezone/vm.c
@@ -412,3 +412,16 @@ int gzvm_arch_map_guest_block(u16 vm_id, int memslot_id, u64 gfn, u64 nr_pages)
return gzvm_hypcall_wrapper(MT_HVC_GZVM_MAP_GUEST_BLOCK, vm_id,
memslot_id, gfn, nr_pages, 0, 0, 0, &res);
}
+
+int gzvm_arch_get_statistics(struct gzvm *gzvm)
+{
+ struct arm_smccc_res res;
+ int ret;
+
+ ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_GET_STATISTICS, gzvm->vm_id,
+ 0, 0, 0, 0, 0, 0, &res);
+
+ gzvm->stat.protected_hyp_mem = ((ret == 0) ? res.a1 : 0);
+ gzvm->stat.protected_shared_mem = ((ret == 0) ? res.a2 : 0);
+ return ret;
+}
diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c
index af5ab8949206..da1c0f478b61 100644
--- a/drivers/virt/geniezone/gzvm_main.c
+++ b/drivers/virt/geniezone/gzvm_main.c
@@ -113,6 +113,11 @@ static int gzvm_drv_probe(struct platform_device *pdev)
ret = gzvm_drv_irqfd_init();
if (ret)
return ret;
+
+ ret = gzvm_drv_debug_init();
+ if (ret)
+ return ret;
+
return 0;
}
@@ -121,6 +126,7 @@ static int gzvm_drv_remove(struct platform_device *pdev)
gzvm_drv_irqfd_exit();
gzvm_destroy_all_vms();
misc_deregister(&gzvm_dev);
+ gzvm_drv_debug_exit();
return 0;
}
diff --git a/drivers/virt/geniezone/gzvm_vm.c b/drivers/virt/geniezone/gzvm_vm.c
index 1af78f161eb3..4861730d555d 100644
--- a/drivers/virt/geniezone/gzvm_vm.c
+++ b/drivers/virt/geniezone/gzvm_vm.c
@@ -11,11 +11,14 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/gzvm_drv.h>
+#include <linux/debugfs.h>
#include "gzvm_common.h"
static DEFINE_MUTEX(gzvm_list_lock);
static LIST_HEAD(gzvm_list);
+static struct dentry *gzvm_debugfs_dir;
+
u64 gzvm_gfn_to_hva_memslot(struct gzvm_memslot *memslot, u64 gfn)
{
u64 offset = gfn - memslot->base_gfn;
@@ -308,6 +311,12 @@ static void gzvm_destroy_all_ppage(struct gzvm *gzvm)
}
}
+static int gzvm_destroy_vm_debugfs(struct gzvm *vm)
+{
+ debugfs_remove_recursive(vm->debug_dir);
+ return 0;
+}
+
static void gzvm_destroy_vm(struct gzvm *gzvm)
{
size_t allocated_size;
@@ -334,6 +343,8 @@ static void gzvm_destroy_vm(struct gzvm *gzvm)
/* No need to lock here becauese it's single-threaded execution */
gzvm_destroy_all_ppage(gzvm);
+ gzvm_destroy_vm_debugfs(gzvm);
+
kfree(gzvm);
}
@@ -391,6 +402,113 @@ static void setup_vm_demand_paging(struct gzvm *vm)
}
}
+static int debugfs_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+/**
+ * hyp_mem_read() - Get size of hypervisor-allocated memory and stage 2 table
+ * @file: Pointer to struct file
+ * @buf: User space buffer for storing the return value
+ * @len: Size of @buf, in bytes
+ * @offset: Pointer to loff_t
+ *
+ * Return: Size of hypervisor-allocated memory and stage 2 table, in bytes
+ */
+static ssize_t hyp_mem_read(struct file *file, char __user *buf, size_t len,
+ loff_t *offset)
+{
+ char tmp_buffer[GZVM_MAX_DEBUGFS_VALUE_SIZE] = {0};
+ struct gzvm *vm = file->private_data;
+ int ret;
+
+ if (*offset == 0) {
+ ret = gzvm_arch_get_statistics(vm);
+ if (ret)
+ return ret;
+ snprintf(tmp_buffer, sizeof(tmp_buffer), "%llu\n",
+ vm->stat.protected_hyp_mem);
+ if (copy_to_user(buf, tmp_buffer, sizeof(tmp_buffer)))
+ return -EFAULT;
+ *offset += sizeof(tmp_buffer);
+ return sizeof(tmp_buffer);
+ }
+ return 0;
+}
+
+/**
+ * shared_mem_read() - Get size of memory shared between host and guest
+ * @file: Pointer to struct file
+ * @buf: User space buffer for storing the return value
+ * @len: Size of @buf, in bytes
+ * @offset: Pointer to loff_t
+ *
+ * Return: Size of memory shared between host and guest, in bytes
+ */
+static ssize_t shared_mem_read(struct file *file, char __user *buf, size_t len,
+ loff_t *offset)
+{
+ char tmp_buffer[GZVM_MAX_DEBUGFS_VALUE_SIZE] = {0};
+ struct gzvm *vm = file->private_data;
+ int ret;
+
+ if (*offset == 0) {
+ ret = gzvm_arch_get_statistics(vm);
+ if (ret)
+ return ret;
+ snprintf(tmp_buffer, sizeof(tmp_buffer), "%llu\n",
+ vm->stat.protected_shared_mem);
+ if (copy_to_user(buf, tmp_buffer, sizeof(tmp_buffer)))
+ return -EFAULT;
+ *offset += sizeof(tmp_buffer);
+ return sizeof(tmp_buffer);
+ }
+ return 0;
+}
+
+static const struct file_operations hyp_mem_fops = {
+ .owner = THIS_MODULE,
+ .open = debugfs_open,
+ .read = hyp_mem_read,
+ .llseek = no_llseek,
+};
+
+static const struct file_operations shared_mem_fops = {
+ .owner = THIS_MODULE,
+ .open = debugfs_open,
+ .read = shared_mem_read,
+ .llseek = no_llseek,
+};
+
+static int gzvm_create_vm_debugfs(struct gzvm *vm)
+{
+ struct dentry *dent;
+ char dir_name[GZVM_MAX_DEBUGFS_DIR_NAME_SIZE];
+
+ if (vm->debug_dir) {
+ pr_warn("VM debugfs directory is duplicated\n");
+ return 0;
+ }
+
+ snprintf(dir_name, sizeof(dir_name), "%d-%d", task_pid_nr(current), vm->vm_id);
+
+ dent = debugfs_lookup(dir_name, gzvm_debugfs_dir);
+ if (dent) {
+ pr_warn("Debugfs directory is duplicated\n");
+ dput(dent);
+ return 0;
+ }
+ dent = debugfs_create_dir(dir_name, gzvm_debugfs_dir);
+ vm->debug_dir = dent;
+
+ debugfs_create_file("protected_shared_mem", 0444, dent, vm, &shared_mem_fops);
+ debugfs_create_file("protected_hyp_mem", 0444, dent, vm, &hyp_mem_fops);
+
+ return 0;
+}
+
static struct gzvm *gzvm_create_vm(unsigned long vm_type)
{
int ret;
@@ -432,6 +550,8 @@ static struct gzvm *gzvm_create_vm(unsigned long vm_type)
list_add(&gzvm->vm_list, &gzvm_list);
mutex_unlock(&gzvm_list_lock);
+ gzvm_create_vm_debugfs(gzvm);
+
pr_debug("VM-%u is created\n", gzvm->vm_id);
return gzvm;
@@ -469,3 +589,20 @@ void gzvm_destroy_all_vms(void)
out:
mutex_unlock(&gzvm_list_lock);
}
+
+int gzvm_drv_debug_init(void)
+{
+ if (!debugfs_initialized())
+ return 0;
+
+ if (!gzvm_debugfs_dir && !debugfs_lookup("gzvm", gzvm_debugfs_dir))
+ gzvm_debugfs_dir = debugfs_create_dir("gzvm", NULL);
+
+ return 0;
+}
+
+void gzvm_drv_debug_exit(void)
+{
+ if (gzvm_debugfs_dir && debugfs_lookup("gzvm", gzvm_debugfs_dir))
+ debugfs_remove_recursive(gzvm_debugfs_dir);
+}
diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h
index 2e50ee3011e8..d532d2d31d43 100644
--- a/include/linux/gzvm_drv.h
+++ b/include/linux/gzvm_drv.h
@@ -47,6 +47,9 @@
#define GZVM_BLOCK_BASED_DEMAND_PAGE_SIZE (2 * 1024 * 1024) /* 2MB */
+#define GZVM_MAX_DEBUGFS_DIR_NAME_SIZE 20
+#define GZVM_MAX_DEBUGFS_VALUE_SIZE 20
+
/* struct mem_region_addr_range - Identical to ffa memory constituent */
struct mem_region_addr_range {
/* the base IPA of the constituent memory region, aligned to 4 kiB */
@@ -89,6 +92,11 @@ struct gzvm_pinned_page {
u64 ipa;
};
+struct gzvm_vm_stat {
+ u64 protected_hyp_mem;
+ u64 protected_shared_mem;
+};
+
struct gzvm {
struct gzvm_vcpu *vcpus[GZVM_MAX_VCPUS];
/* userspace tied to this vm */
@@ -133,6 +141,9 @@ struct gzvm {
struct rb_root pinned_pages;
/* lock for memory operations */
struct mutex mem_lock;
+
+ struct gzvm_vm_stat stat;
+ struct dentry *debug_dir;
};
long gzvm_dev_ioctl_check_extension(struct gzvm *gzvm, unsigned long args);
@@ -154,6 +165,7 @@ int gzvm_arch_destroy_vm(u16 vm_id);
int gzvm_arch_map_guest(u16 vm_id, int memslot_id, u64 pfn, u64 gfn,
u64 nr_pages);
int gzvm_arch_map_guest_block(u16 vm_id, int memslot_id, u64 gfn, u64 nr_pages);
+int gzvm_arch_get_statistics(struct gzvm *gzvm);
int gzvm_vm_ioctl_arch_enable_cap(struct gzvm *gzvm,
struct gzvm_enable_cap *cap,
void __user *argp);
@@ -175,6 +187,9 @@ int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason);
int gzvm_arch_destroy_vcpu(u16 vm_id, int vcpuid);
int gzvm_arch_inform_exit(u16 vm_id);
+int gzvm_drv_debug_init(void);
+void gzvm_drv_debug_exit(void);
+
int gzvm_find_memslot(struct gzvm *vm, u64 gpa);
int gzvm_handle_page_fault(struct gzvm_vcpu *vcpu);
bool gzvm_handle_guest_exception(struct gzvm_vcpu *vcpu);
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2024-01-29 8:35 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-29 8:32 [PATCH v9 00/21] GenieZone hypervisor drivers Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 01/21] virt: geniezone: enable gzvm-ko in defconfig Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 02/21] docs: geniezone: Introduce GenieZone hypervisor Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 03/21] dt-bindings: hypervisor: Add MediaTek " Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 04/21] virt: geniezone: Add GenieZone hypervisor driver Yi-De Wu
2024-02-01 9:44 ` AngeloGioacchino Del Regno
2024-01-29 8:32 ` [PATCH v9 05/21] virt: geniezone: Add vm support Yi-De Wu
2024-02-01 9:44 ` AngeloGioacchino Del Regno
2024-01-29 8:32 ` [PATCH v9 06/21] virt: geniezone: Add set_user_memory_region for vm Yi-De Wu
2024-02-01 9:44 ` AngeloGioacchino Del Regno
2024-01-29 8:32 ` [PATCH v9 07/21] virt: geniezone: Add vm capability check Yi-De Wu
2024-02-01 9:44 ` AngeloGioacchino Del Regno
2024-04-03 8:50 ` Yi-De Wu (吳一德)
2024-01-29 8:32 ` [PATCH v9 08/21] virt: geniezone: Optimize performance of protected VM memory Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 09/21] virt: geniezone: Add vcpu support Yi-De Wu
2024-02-01 9:44 ` AngeloGioacchino Del Regno
2024-01-29 8:32 ` [PATCH v9 10/21] virt: geniezone: Add irqchip support for virtual interrupt injection Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 11/21] virt: geniezone: Add irqfd support Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 12/21] virt: geniezone: Add ioeventfd support Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 13/21] virt: geniezone: Add memory region support Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 14/21] virt: geniezone: Add dtb config support Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 15/21] virt: geniezone: Add demand paging support Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 16/21] virt: geniezone: Add block-based " Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 17/21] virt: geniezone: Add memory pin/unpin support Yi-De Wu
2024-01-29 8:32 ` [PATCH v9 18/21] virt: geniezone: Add memory relinquish support Yi-De Wu
2024-01-29 8:33 ` Yi-De Wu [this message]
2024-01-29 8:33 ` [PATCH v9 20/21] virt: geniezone: Add tracing support for hyp call and vcpu exit_reason Yi-De Wu
2024-01-29 8:33 ` [PATCH v9 21/21] virt: geniezone: Enable PTP for synchronizing time between host and guest VMs Yi-De Wu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240129083302.26044-20-yi-de.wu@mediatek.com \
--to=yi-de.wu@mediatek.com \
--cc=angelogioacchino.delregno@collabora.com \
--cc=catalin.marinas@arm.com \
--cc=chi-shen.yeh@mediatek.com \
--cc=conor+dt@kernel.org \
--cc=corbet@lwn.net \
--cc=dbrazdil@google.com \
--cc=devicetree@vger.kernel.org \
--cc=kevenny.hsieh@mediatek.com \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=liju-clr.chen@mediatek.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=matthias.bgg@gmail.com \
--cc=my.chuang@mediatek.com \
--cc=netdev@vger.kernel.org \
--cc=peilun.suei@mediatek.com \
--cc=quic_tsoni@quicinc.com \
--cc=richardcochran@gmail.com \
--cc=robh+dt@kernel.org \
--cc=shawn.hsiao@mediatek.com \
--cc=will@kernel.org \
--cc=yingshiuan.pan@mediatek.com \
--cc=ze-yu.wang@mediatek.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox