@@ -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);
/*
@@ -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)
{
@@ -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;
@@ -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
@@ -92,6 +92,9 @@ config STATIC_MEMORY
If unsure, say N.
+config VMF
+ bool "Virtual Memory Fuse Support"
+
menu "Speculative hardening"
config INDIRECT_THUNK
@@ -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
new file mode 100644
@@ -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;
+}
@@ -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)
new file mode 100644
@@ -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:
+ */
@@ -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
+
/* ` } */
/*
new file mode 100644
@@ -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__ */