@@ -6,6 +6,7 @@ config X86
def_bool y
select ACPI
select ACPI_LEGACY_TABLES_LOOKUP
+ select ALTERNATIVE_CALL
select ARCH_SUPPORTS_INT128
select CORE_PARKING
select HAS_ALTERNATIVE
@@ -22,6 +22,9 @@ config GRANT_TABLE
If unsure, say Y.
+config ALTERNATIVE_CALL
+ bool
+
config HAS_ALTERNATIVE
bool
new file mode 100644
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef XEN_ALTERNATIVE_CALL
+#define XEN_ALTERNATIVE_CALL
+
+/*
+ * Some subsystems in Xen may have multiple implementions, which can be
+ * resolved to a single implementation at boot time. By default, this will
+ * result in the use of function pointers.
+ *
+ * Some architectures may have mechanisms for dynamically modifying .text.
+ * Using this mechnaism, function pointers can be converted to direct calls
+ * which are typically more efficient at runtime.
+ *
+ * For architectures to support:
+ *
+ * - Implement alternative_{,v}call() in asm/alternative.h. Code generation
+ * requirements are to emit a function pointer call at build time, and stash
+ * enough metadata to simplify the call at boot once the implementation has
+ * been resolved.
+ * - Select ALTERNATIVE_CALL in Kconfig.
+ *
+ * To use:
+ *
+ * Consider the following simplified example.
+ *
+ * 1) struct foo_ops __alt_call_maybe_initdata ops;
+ *
+ * 2) const struct foo_ops __initconstrel foo_a_ops = { ... };
+ * const struct foo_ops __initconstrel foo_b_ops = { ... };
+ *
+ * void __init foo_init(void)
+ * {
+ * ...
+ * if ( use_impl_a )
+ * ops = *foo_a_ops;
+ * else if ( use_impl_b )
+ * ops = *foo_b_ops;
+ * ...
+ * }
+ *
+ * 3) alternative_call(ops.bar, ...);
+ *
+ * There needs to a single ops object (1) which will eventually contain the
+ * function pointers. This should be populated in foo's init() function (2)
+ * by one of the available implementations. To call functions, use
+ * alternative_{,v}call() referencing the main ops object (3).
+ */
+
+#ifdef CONFIG_ALTERNATIVE_CALL
+
+#include <asm/alternative.h>
+
+#define __alt_call_maybe_initdata __initdata
+
+#else
+
+#define alternative_call(func, args...) (func)(args)
+#define alternative_vcall(func, args...) (func)(args)
+
+#define __alt_call_maybe_initdata __read_mostly
+
+#endif /* !CONFIG_ALTERNATIVE_CALL */
+#endif /* XEN_ALTERNATIVE_CALL */