[RFC 1/4] Add VMF Hypercall

Smith, Jackson posted 4 patches 1 year, 11 months ago
[RFC 1/4] Add VMF Hypercall
Posted by Smith, Jackson 1 year, 11 months ago
This commit introduces a new vmf_op hypercall. If desired, could be merged
into an exisiting hypercall.

Also, introduce a VMF Kconfig option and xen/vmf.h, defining the arch specific
functions that must be implmented to support vmf.
---
 tools/include/xenctrl.h                 |   2 +
 tools/libs/ctrl/xc_private.c            |   5 ++
 tools/libs/ctrl/xc_private.h            |   5 ++
 xen/arch/x86/guest/xen/hypercall_page.S |   2 +
 xen/common/Kconfig                      |   3 +
 xen/common/Makefile                     |   1 +
 xen/common/vmf.c                        | 111 ++++++++++++++++++++++++++++++++
 xen/include/hypercall-defs.c            |   6 ++
 xen/include/public/vmf.h                |  24 +++++++
 xen/include/public/xen.h                |   3 +
 xen/include/xen/vmf.h                   |  20 ++++++
 11 files changed, 182 insertions(+)
 create mode 100644 xen/common/vmf.c
 create mode 100644 xen/include/public/vmf.h
 create mode 100644 xen/include/xen/vmf.h

diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h
index 2303787..804ddba 100644
--- a/tools/include/xenctrl.h
+++ b/tools/include/xenctrl.h
@@ -1604,6 +1604,8 @@ long xc_memory_op(xc_interface *xch, unsigned int cmd, void *arg, size_t len);
 
 int xc_version(xc_interface *xch, int cmd, void *arg);
 
+int xc_vmf_op(xc_interface *xch, unsigned int cmd, uint32_t domid);
+
 int xc_flask_op(xc_interface *xch, xen_flask_op_t *op);
 
 /*
diff --git a/tools/libs/ctrl/xc_private.c b/tools/libs/ctrl/xc_private.c
index 2f99a7d..44fe9ba 100644
--- a/tools/libs/ctrl/xc_private.c
+++ b/tools/libs/ctrl/xc_private.c
@@ -555,6 +555,11 @@ int xc_version(xc_interface *xch, int cmd, void *arg)
     return rc;
 }
 
+int xc_vmf_op(xc_interface *xch, unsigned int cmd, uint32_t domid)
+{
+    return do_vmf_op(xch, cmd, domid);
+}
+
 unsigned long xc_make_page_below_4G(
     xc_interface *xch, uint32_t domid, unsigned long mfn)
 {
diff --git a/tools/libs/ctrl/xc_private.h b/tools/libs/ctrl/xc_private.h
index ed960c6..fb72cb4 100644
--- a/tools/libs/ctrl/xc_private.h
+++ b/tools/libs/ctrl/xc_private.h
@@ -222,6 +222,11 @@ static inline int do_xen_version(xc_interface *xch, int cmd, xc_hypercall_buffer
                     cmd, HYPERCALL_BUFFER_AS_ARG(dest));
 }
 
+static inline int do_vmf_op(xc_interface *xch, unsigned int cmd, uint32_t domid)
+{
+    return xencall2(xch->xcall, __HYPERVISOR_vmf_op, cmd, domid);
+}
+
 static inline int do_physdev_op(xc_interface *xch, int cmd, void *op, size_t len)
 {
     int ret = -1;
diff --git a/xen/arch/x86/guest/xen/hypercall_page.S b/xen/arch/x86/guest/xen/hypercall_page.S
index 9958d02..2efdd58 100644
--- a/xen/arch/x86/guest/xen/hypercall_page.S
+++ b/xen/arch/x86/guest/xen/hypercall_page.S
@@ -70,6 +70,8 @@ DECLARE_HYPERCALL(arch_5)
 DECLARE_HYPERCALL(arch_6)
 DECLARE_HYPERCALL(arch_7)
 
+DECLARE_HYPERCALL(vmf_op)
+
 /*
  * Local variables:
  * tab-width: 8
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index f1ea319..3bf92b8 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -92,6 +92,9 @@ config STATIC_MEMORY
 
 	  If unsure, say N.
 
+config VMF
+	bool "Virtual Memory Fuse Support"
+
 menu "Speculative hardening"
 
 config INDIRECT_THUNK
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 3baf83d..fb9118d 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -48,6 +48,7 @@ obj-y += timer.o
 obj-$(CONFIG_TRACEBUFFER) += trace.o
 obj-y += version.o
 obj-y += virtual_region.o
+obj-$(CONFIG_VMF) += vmf.o
 obj-y += vm_event.o
 obj-y += vmap.o
 obj-y += vsprintf.o
diff --git a/xen/common/vmf.c b/xen/common/vmf.c
new file mode 100644
index 0000000..20c61d1
--- /dev/null
+++ b/xen/common/vmf.c
@@ -0,0 +1,111 @@
+/******************************************************************************
+ * vmf.c
+ * 
+ * Common implementation of the VMF hypercall
+ */
+
+#include <xen/lib.h>
+#include <xen/sched.h>
+
+#include <public/vmf.h>
+#include <xen/vmf.h>
+
+static void dump_domain_vcpus(struct domain *d)
+{
+    struct vcpu *v;
+    int i;
+
+    if (d == NULL) {
+        printk("NULL\n");
+        return;
+    }
+
+    printk("Domain: %d (%d vcpus)\n", d->domain_id, d->max_vcpus);
+#if defined(CONFIG_ARM_64)
+    printk("  vttbr: 0x%lx\n", d->arch.p2m.vttbr);
+#endif
+
+    i = 0;
+    for_each_vcpu(d, v)
+    {
+        printk("  vcpu [%d: id=%d, proc=%d]: \n", i++, v->vcpu_id, v->processor);
+        /* archvcpu for arm has: */
+#if defined(CONFIG_ARM_64)
+        printk("    .ttbr0     is 0x%lx\n", v->arch.ttbr0);
+        printk("    .ttbr1     is 0x%lx\n", v->arch.ttbr1);
+#endif
+    }
+}
+
+static void dump_domains(void)
+{
+    struct domain *d;
+
+    for_each_domain(d)
+        dump_domain_vcpus(d);
+
+    /* Dump system domains */
+    printk("IDLE DOMAIN:\n");
+    dump_domain_vcpus(idle_vcpu[0]->domain);
+    printk("HARDWARE DOMAIN:\n");
+    dump_domain_vcpus(hardware_domain);
+    printk("XEN DOMAIN:\n");
+    dump_domain_vcpus(dom_xen);
+    printk("IO DOMAIN:\n");
+    dump_domain_vcpus(dom_io);
+}
+
+long do_vmf_op(unsigned int cmd, domid_t domid)
+{
+    int ret = 0;
+    struct domain *d = NULL;
+
+    printk("VMF hypercall: ");
+
+    if (domid == DOMID_IDLE) {
+        printk("Xen\n");
+    } else if ((domid < DOMID_FIRST_RESERVED) && (d = get_domain_by_id(domid))) {
+        printk("Domain(%d)\n", domid);
+    } else {
+        printk("Invalid domain id (%d)\n", domid);
+        ret = -1;
+        goto out;
+    }
+
+    switch (cmd) {
+    case XENVMF_dump_info:
+        if (d) {
+            vmf_dump_domain_info(d);
+        } else {
+            dump_domains();
+            vmf_dump_xen_info();
+        }
+        break;
+
+    case XENVMF_dump_tables:
+        if (d)
+            vmf_dump_domain_tables(d);
+        else
+            vmf_dump_xen_tables();
+        break;
+
+    case XENVMF_unmap:
+        printk("BLOW VIRTUAL MEMORY FUSE:\n");
+        if (d) {
+            printk("Unmapping Domain(%d)\n", d->domain_id);
+            vmf_unmap_guest(d);
+        } else {
+            printk("Locking Virtual Memory Configuration\n");
+            vmf_lock_xen_pgtables();
+        }
+        break;
+
+    default:
+        printk("Not Implemented\n");
+        break;
+    }
+
+out:
+    printk("Done!\n");
+    return ret;
+}
diff --git a/xen/include/hypercall-defs.c b/xen/include/hypercall-defs.c
index 1896121..fb61bc6 100644
--- a/xen/include/hypercall-defs.c
+++ b/xen/include/hypercall-defs.c
@@ -166,6 +166,9 @@ vm_assist(unsigned int cmd, unsigned int type)
 event_channel_op(int cmd, void *arg)
 mmuext_op(mmuext_op_t *uops, unsigned int count, unsigned int *pdone, unsigned int foreigndom)
 multicall(multicall_entry_t *call_list, unsigned int nr_calls)
+#if defined(CONFIG_VMF)
+vmf_op(unsigned int cmd, domid_t domid)
+#endif
 #ifdef CONFIG_PV
 mmu_update(mmu_update_t *ureqs, unsigned int count, unsigned int *pdone, unsigned int foreigndom)
 stack_switch(unsigned long ss, unsigned long esp)
@@ -239,6 +242,9 @@ update_va_mapping                  compat   do       -        -        -
 set_timer_op                       compat   do       compat   do       -
 event_channel_op_compat            do       do       -        -        dep
 xen_version                        compat   do       compat   do       do
+#if defined(CONFIG_VMF)
+vmf_op                             do       do       do       do       do
+#endif
 console_io                         do       do       do       do       do
 physdev_op_compat                  compat   do       -        -        dep
 #if defined(CONFIG_GRANT_TABLE)
diff --git a/xen/include/public/vmf.h b/xen/include/public/vmf.h
new file mode 100644
index 0000000..a5ec004
--- /dev/null
+++ b/xen/include/public/vmf.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: MIT */
+/******************************************************************************
+ * vmf.h
+ *
+ */
+
+#ifndef __XEN_PUBLIC_VMF_H__
+#define __XEN_PUBLIC_VMF_H__
+
+#define XENVMF_dump_info 1
+#define XENVMF_dump_tables 2
+#define XENVMF_unmap 11
+
+#endif /* __XEN_PUBLIC_VMF_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
index 920567e..077000c 100644
--- a/xen/include/public/xen.h
+++ b/xen/include/public/xen.h
@@ -125,6 +125,9 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
 #define __HYPERVISOR_arch_6               54
 #define __HYPERVISOR_arch_7               55
 
+/* custom vmf hypercall */
+#define __HYPERVISOR_vmf_op               56
+
 /* ` } */
 
 /*
diff --git a/xen/include/xen/vmf.h b/xen/include/xen/vmf.h
new file mode 100644
index 0000000..f4b350c
--- /dev/null
+++ b/xen/include/xen/vmf.h
@@ -0,0 +1,20 @@
+/******************************************************************************
+ * vmf.h
+ * 
+ * Public VMF interface to be implemented in arch specific code
+ */
+
+#ifndef __XEN_VMF_H__
+#define __XEN_VMF_H__
+
+struct domain;
+
+void vmf_dump_xen_info(void);
+void vmf_dump_domain_info(struct domain *d);
+void vmf_dump_xen_tables(void);
+void vmf_dump_domain_tables(struct domain *d);
+
+void vmf_unmap_guest(struct domain *d);
+void vmf_lock_xen_pgtables(void);
+
+#endif /* __XEN_VMF_H__ */
-- 
2.7.4

Re: [RFC 1/4] Add VMF Hypercall
Posted by Jan Beulich 1 year, 11 months ago
On 13.12.2022 20:50, Smith, Jackson wrote:
> This commit introduces a new vmf_op hypercall. If desired, could be merged
> into an exisiting hypercall.
> 
> Also, introduce a VMF Kconfig option and xen/vmf.h, defining the arch specific
> functions that must be implmented to support vmf.

Neither here nor in the public interface header you describe what this is
intended to do (including both present sub-ops as well as future ones,
which - judging from the numbering - appear to exist somewhere). Therefore
there is too little context here to make any judgement.

Jan