This adds a method to call init/exit functions similar to the kernel's init functions. Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx> --- tools/kvm/include/kvm/util-init.h | 51 +++++++++++++++++++++++++++++ tools/kvm/util/init.c | 69 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 tools/kvm/include/kvm/util-init.h create mode 100644 tools/kvm/util/init.c diff --git a/tools/kvm/include/kvm/util-init.h b/tools/kvm/include/kvm/util-init.h new file mode 100644 index 0000000..beccb4e --- /dev/null +++ b/tools/kvm/include/kvm/util-init.h @@ -0,0 +1,51 @@ +#ifndef KVM__UTIL_INIT_H +#define KVM__UTIL_INIT_H + +struct kvm; + +struct init_item { + struct hlist_node n; + const char *fn_name; + int (*init)(struct kvm *); +}; + +int init_list__init(struct kvm *kvm); +int init_list__exit(struct kvm *kvm); + +int init_list_add(struct init_item *t, int (*init)(struct kvm *), + int priority, const char *name); +int exit_list_add(struct init_item *t, int (*init)(struct kvm *), + int priority, const char *name); + +#define __init_list_add(cb, l) \ +static void __attribute__ ((constructor)) __init__##cb(void) \ +{ \ + static char name[] = #cb; \ + static struct init_item t; \ + init_list_add(&t, cb, l, name); \ +} + +#define __exit_list_add(cb, l) \ +static void __attribute__ ((constructor)) __init__##cb(void) \ +{ \ + static char name[] = #cb; \ + static struct init_item t; \ + exit_list_add(&t, cb, l, name); \ +} + +#define core_init(cb) __init_list_add(cb, 0) +#define base_init(cb) __init_list_add(cb, 2) +#define dev_base_init(cb) __init_list_add(cb, 4) +#define dev_init(cb) __init_list_add(cb, 5) +#define virtio_dev_init(cb) __init_list_add(cb, 6) +#define firmware_init(cb) __init_list_add(cb, 7) +#define late_init(cb) __init_list_add(cb, 9) + +#define core_exit(cb) __exit_list_add(cb, 0) +#define base_exit(cb) __exit_list_add(cb, 2) +#define dev_base_exit(cb) __exit_list_add(cb, 4) +#define dev_exit(cb) __exit_list_add(cb, 5) +#define virtio_dev_exit(cb) __exit_list_add(cb, 6) +#define firmware_exit(cb) __exit_list_add(cb, 7) +#define late_exit(cb) __exit_list_add(cb, 9) +#endif diff --git a/tools/kvm/util/init.c b/tools/kvm/util/init.c new file mode 100644 index 0000000..b3face1 --- /dev/null +++ b/tools/kvm/util/init.c @@ -0,0 +1,69 @@ +#include <linux/list.h> +#include <linux/kernel.h> + +#include "kvm/kvm.h" +#include "kvm/util-init.h" + +#define PRIORITY_LISTS 10 + +static struct hlist_head init_lists[PRIORITY_LISTS]; +static struct hlist_head exit_lists[PRIORITY_LISTS]; + +int init_list_add(struct init_item *t, int (*init)(struct kvm *), + int priority, const char *name) +{ + t->init = init; + t->fn_name = name; + hlist_add_head(&t->n, &init_lists[priority]); + + return 0; +} + +int exit_list_add(struct init_item *t, int (*init)(struct kvm *), + int priority, const char *name) +{ + t->init = init; + t->fn_name = name; + hlist_add_head(&t->n, &exit_lists[priority]); + + return 0; +} + +int init_list__init(struct kvm *kvm) +{ + unsigned int i; + int r = 0; + struct hlist_node *n; + struct init_item *t; + + for (i = 0; i < ARRAY_SIZE(init_lists); i++) + hlist_for_each_entry(t, n, &init_lists[i], n) { + r = t->init(kvm); + if (r < 0) { + pr_warning("Failed init: %s\n", t->fn_name); + goto fail; + } + } + +fail: + return r; +} + +int init_list__exit(struct kvm *kvm) +{ + int i; + int r = 0; + struct hlist_node *n; + struct init_item *t; + + for (i = ARRAY_SIZE(exit_lists) - 1; i >= 0; i--) + hlist_for_each_entry(t, n, &exit_lists[i], n) { + r = t->init(kvm); + if (r < 0) { + pr_warning("%s failed.\n", t->fn_name); + goto fail; + } + } +fail: + return r; +} -- 1.7.12 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html