int xc_livepatch_unload(xc_interface *xch, char *name, uint32_t timeout, uint32_t flags);
int xc_livepatch_replace(xc_interface *xch, char *name, uint32_t timeout, uint32_t flags);
+/* Dummy hypercall to test livepatch functionality. */
+int xc_livepatch_test(xc_interface *xch, uint32_t *result);
+
/*
* Ensure cache coherency after memory modifications. A call to this function
* is only required on ARM as the x86 architecture provides cache coherency
return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_REPLACE, timeout, flags);
}
+int xc_livepatch_test(xc_interface *xch, uint32_t *result)
+{
+ int rc;
+ DECLARE_SYSCTL = {
+ .cmd = XEN_SYSCTL_livepatch_op,
+ .u.livepatch.cmd = XEN_SYSCTL_LIVEPATCH_TEST,
+ };
+
+ rc = do_sysctl(xch, &sysctl);
+ if ( !rc )
+ *result = sysctl.u.livepatch.u.test.result;
+
+ return rc;
+}
+
/*
* Local variables:
* mode: C
" replace <name> apply <name> patch and revert all others.\n"
" unload <name> unload name <name> patch.\n"
" load <file> [flags] upload and apply <file> with name as the <file> name\n"
+ " test print the result of the test hypercall (for testing purposes only)\n"
" Supported flags:\n"
" --nodeps Disable inter-module buildid dependency check.\n"
" Check only against hypervisor buildid.\n",
return rc;
}
+static int test_func(int argc, char *argv[])
+{
+ int rc;
+ uint32_t result;
+
+ if ( argc != 0 )
+ {
+ show_help();
+ return -1;
+ }
+
+ rc = xc_livepatch_test(xch, &result);
+ if ( rc )
+ {
+ fprintf(stderr, "test operation failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ printf("%u\n", result);
+
+ return 0;
+}
+
/*
* These are also functions in action_options that are called in case
* none of the ones in main_options match.
{ "list", list_func },
{ "upload", upload_func },
{ "load", load_func },
+ { "test", test_func },
};
int main(int argc, char *argv[])
obj-y += keyhandler.o
obj-$(CONFIG_KEXEC) += kexec.o
obj-$(CONFIG_KEXEC) += kimage.o
-obj-$(CONFIG_LIVEPATCH) += livepatch.o livepatch_elf.o
+obj-$(CONFIG_LIVEPATCH) += livepatch.o livepatch_elf.o livepatch-test.o
obj-$(CONFIG_MEM_ACCESS) += mem_access.o
obj-y += memory.o
obj-y += multicall.o
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* Dummy file for testing livepatch functionality. */
+#include <xen/livepatch.h>
+
+int livepatch_test(struct xen_sysctl_livepatch_test *test)
+{
+ test->result = 2;
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
rc = livepatch_action(&livepatch->u.action);
break;
+ case XEN_SYSCTL_LIVEPATCH_TEST:
+ rc = livepatch_test(&livepatch->u.test);
+ break;
+
default:
rc = -EOPNOTSUPP;
break;
uint32_t pad; /* IN: Always zero. */
};
+/* Dummy hypercall used for testing the generation of live patches. */
+#define XEN_SYSCTL_LIVEPATCH_TEST 4
+struct xen_sysctl_livepatch_test {
+ uint32_t result; /* OUT: dummy result for testing. */
+};
+
struct xen_sysctl_livepatch_op {
uint32_t cmd; /* IN: XEN_SYSCTL_LIVEPATCH_*. */
uint32_t pad; /* IN: Always zero. */
struct xen_sysctl_livepatch_list list;
struct xen_sysctl_livepatch_get get;
struct xen_sysctl_livepatch_action action;
+ struct xen_sysctl_livepatch_test test;
} u;
};
struct livepatch_elf_sym;
struct xen_sysctl_livepatch_op;
+#include <xen/types.h>
+
#include <xen/elfstructs.h>
#include <xen/errno.h> /* For -ENOSYS or -EOVERFLOW */
#ifdef CONFIG_LIVEPATCH
arch_livepatch_revert(func);
func->applied = LIVEPATCH_FUNC_NOT_APPLIED;
}
+
+int livepatch_test(struct xen_sysctl_livepatch_test *test);
#else
/*
--- /dev/null
+diff --git a/xen/common/livepatch-test.c b/xen/common/livepatch-test.c
+index 05b638b2ac..876173ab6f 100644
+--- a/xen/common/livepatch-test.c
++++ b/xen/common/livepatch-test.c
+@@ -5,7 +5,7 @@
+
+ int livepatch_test(struct xen_sysctl_livepatch_test *test)
+ {
+- test->result = 1;
++ test->result = 2;
+ return 0;
+ }
+