summaryrefslogtreecommitdiff
path: root/include/linux/kho_radix_tree.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/kho_radix_tree.h')
-rw-r--r--include/linux/kho_radix_tree.h90
1 files changed, 90 insertions, 0 deletions
diff --git a/include/linux/kho_radix_tree.h b/include/linux/kho_radix_tree.h
new file mode 100644
index 000000000000..fcd69639721b
--- /dev/null
+++ b/include/linux/kho_radix_tree.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _LINUX_KHO_RADIX_TREE_H
+#define _LINUX_KHO_RADIX_TREE_H
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/mutex_types.h>
+#include <linux/types.h>
+
+/**
+ * DOC: Kexec Handover Radix Tree
+ *
+ * This is a radix tree implementation for tracking numeric keys across kexec
+ * transitions. It was developed for the KHO preserved memory map but is
+ * designed for broader use by any subsystem that needs to track keys.
+ * Conceptually speaking, the data structure is similar to a set. It tracks the
+ * presence or absence of numeric keys.
+ *
+ * The radix tree is a multi-level tree where leaf nodes are bitmaps
+ * representing individual keys.
+ *
+ * For the KHO preserved memory map, to allow pages of different sizes (orders)
+ * to be stored efficiently in a single tree, it uses a unique key encoding
+ * scheme. Each key is an unsigned long that combines a page's physical address
+ * and its order.
+ *
+ * Client code is responsible for allocating the root node of the tree,
+ * initializing the mutex lock, and managing its lifecycle. It must use the
+ * tree data structures defined in the KHO ABI,
+ * `include/linux/kho/abi/kexec_handover.h`.
+ */
+
+struct kho_radix_node;
+
+struct kho_radix_tree {
+ struct kho_radix_node *root;
+ struct mutex lock; /* protects the tree's structure and root pointer */
+};
+
+/**
+ * struct kho_radix_walk_cb - Callbacks for KHO radix tree walk.
+ * @leaf: Called on each present key in the radix tree.
+ * @node: Called on each node of the radix tree itself. Receives the
+ * physical address of the page containing the node.
+ *
+ * For each callback, a return value of 0 continues the walk and a non-zero
+ * return value is directly returned to the caller.
+ */
+struct kho_radix_walk_cb {
+ int (*leaf)(unsigned long key, void *data);
+ int (*node)(phys_addr_t phys, void *data);
+};
+
+#ifdef CONFIG_KEXEC_HANDOVER
+
+int kho_radix_add_key(struct kho_radix_tree *tree, unsigned long key);
+void kho_radix_del_key(struct kho_radix_tree *tree, unsigned long key);
+int kho_radix_walk_tree(struct kho_radix_tree *tree,
+ const struct kho_radix_walk_cb *cb, void *data);
+int kho_radix_init_tree(struct kho_radix_tree *tree, struct kho_radix_node *root);
+void kho_radix_destroy_tree(struct kho_radix_tree *tree);
+
+#else /* #ifdef CONFIG_KEXEC_HANDOVER */
+
+static inline int kho_radix_add_key(struct kho_radix_tree *tree, unsigned long key)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void kho_radix_del_key(struct kho_radix_tree *tree,
+ unsigned long key) { }
+
+static inline int kho_radix_walk_tree(struct kho_radix_tree *tree,
+ const struct kho_radix_walk_cb *cb, void *data)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int kho_radix_init_tree(struct kho_radix_tree *tree,
+ struct kho_radix_node *root)
+{
+ return 0;
+}
+
+static inline void kho_radix_destroy_tree(struct kho_radix_tree *tree) { }
+
+#endif /* #ifdef CONFIG_KEXEC_HANDOVER */
+
+#endif /* _LINUX_KHO_RADIX_TREE_H */