150cb6dc9SSasha Levin #include <linux/list.h>
250cb6dc9SSasha Levin #include <linux/kernel.h>
350cb6dc9SSasha Levin
450cb6dc9SSasha Levin #include "kvm/kvm.h"
550cb6dc9SSasha Levin #include "kvm/util-init.h"
650cb6dc9SSasha Levin
750cb6dc9SSasha Levin #define PRIORITY_LISTS 10
850cb6dc9SSasha Levin
950cb6dc9SSasha Levin static struct hlist_head init_lists[PRIORITY_LISTS];
1050cb6dc9SSasha Levin static struct hlist_head exit_lists[PRIORITY_LISTS];
1150cb6dc9SSasha Levin
init_list_add(struct init_item * t,int (* init)(struct kvm *),int priority,const char * name)1250cb6dc9SSasha Levin int init_list_add(struct init_item *t, int (*init)(struct kvm *),
1350cb6dc9SSasha Levin int priority, const char *name)
1450cb6dc9SSasha Levin {
1550cb6dc9SSasha Levin t->init = init;
1650cb6dc9SSasha Levin t->fn_name = name;
1750cb6dc9SSasha Levin hlist_add_head(&t->n, &init_lists[priority]);
1850cb6dc9SSasha Levin
1950cb6dc9SSasha Levin return 0;
2050cb6dc9SSasha Levin }
2150cb6dc9SSasha Levin
exit_list_add(struct init_item * t,int (* init)(struct kvm *),int priority,const char * name)2250cb6dc9SSasha Levin int exit_list_add(struct init_item *t, int (*init)(struct kvm *),
2350cb6dc9SSasha Levin int priority, const char *name)
2450cb6dc9SSasha Levin {
2550cb6dc9SSasha Levin t->init = init;
2650cb6dc9SSasha Levin t->fn_name = name;
2750cb6dc9SSasha Levin hlist_add_head(&t->n, &exit_lists[priority]);
2850cb6dc9SSasha Levin
2950cb6dc9SSasha Levin return 0;
3050cb6dc9SSasha Levin }
3150cb6dc9SSasha Levin
init_list__init(struct kvm * kvm)3250cb6dc9SSasha Levin int init_list__init(struct kvm *kvm)
3350cb6dc9SSasha Levin {
3450cb6dc9SSasha Levin unsigned int i;
3550cb6dc9SSasha Levin int r = 0;
3650cb6dc9SSasha Levin struct init_item *t;
3750cb6dc9SSasha Levin
3850cb6dc9SSasha Levin for (i = 0; i < ARRAY_SIZE(init_lists); i++)
39*a24ecd1fSMarc Zyngier hlist_for_each_entry(t, &init_lists[i], n) {
4050cb6dc9SSasha Levin r = t->init(kvm);
4150cb6dc9SSasha Levin if (r < 0) {
4250cb6dc9SSasha Levin pr_warning("Failed init: %s\n", t->fn_name);
4350cb6dc9SSasha Levin goto fail;
4450cb6dc9SSasha Levin }
4550cb6dc9SSasha Levin }
4650cb6dc9SSasha Levin
4750cb6dc9SSasha Levin fail:
4850cb6dc9SSasha Levin return r;
4950cb6dc9SSasha Levin }
5050cb6dc9SSasha Levin
init_list__exit(struct kvm * kvm)5150cb6dc9SSasha Levin int init_list__exit(struct kvm *kvm)
5250cb6dc9SSasha Levin {
5350cb6dc9SSasha Levin int i;
5450cb6dc9SSasha Levin int r = 0;
5550cb6dc9SSasha Levin struct init_item *t;
5650cb6dc9SSasha Levin
5750cb6dc9SSasha Levin for (i = ARRAY_SIZE(exit_lists) - 1; i >= 0; i--)
58*a24ecd1fSMarc Zyngier hlist_for_each_entry(t, &exit_lists[i], n) {
5950cb6dc9SSasha Levin r = t->init(kvm);
6050cb6dc9SSasha Levin if (r < 0) {
6150cb6dc9SSasha Levin pr_warning("%s failed.\n", t->fn_name);
6250cb6dc9SSasha Levin goto fail;
6350cb6dc9SSasha Levin }
6450cb6dc9SSasha Levin }
6550cb6dc9SSasha Levin fail:
6650cb6dc9SSasha Levin return r;
6750cb6dc9SSasha Levin }
68