1 /*
2  * Copyright (c) 2021 EPAM Systems
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/arch/arm64/hypercall.h>
8 #include <zephyr/xen/events.h>
9 #include <zephyr/xen/generic.h>
10 #include <zephyr/xen/public/xen.h>
11 #include <zephyr/xen/public/memory.h>
12 
13 #include <zephyr/device.h>
14 #include <zephyr/init.h>
15 #include <zephyr/kernel.h>
16 #include <zephyr/kernel/thread.h>
17 #include <zephyr/logging/log.h>
18 
19 LOG_MODULE_REGISTER(xen_enlighten);
20 
21 /*
22  * During Xen Enlighten initialization we need to have allocated memory page,
23  * where hypervisor shared_info will be mapped. k_aligned_alloc() is not
24  * available on PRE_KERNEL_1 stage, so we will use statically allocated buffer,
25  * which will be casted to 'struct shared_info'. It is needed to initialize Xen
26  * event channels as soon as possible after start.
27  */
28 static uint8_t shared_info_buf[XEN_PAGE_SIZE] __aligned(XEN_PAGE_SIZE);
29 
30 /* Remains NULL until mapping will be finished by Xen */
31 shared_info_t *HYPERVISOR_shared_info;
32 
xen_map_shared_info(const shared_info_t * shared_page)33 static int xen_map_shared_info(const shared_info_t *shared_page)
34 {
35 	struct xen_add_to_physmap xatp;
36 
37 	xatp.domid = DOMID_SELF;
38 	xatp.idx = 0;
39 	xatp.space = XENMAPSPACE_shared_info;
40 	xatp.gpfn = (((xen_pfn_t) shared_page) >> XEN_PAGE_SHIFT);
41 
42 	return HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
43 }
44 
xen_enlighten_init(void)45 static int xen_enlighten_init(void)
46 {
47 	int ret = 0;
48 	shared_info_t *info = (shared_info_t *) shared_info_buf;
49 
50 	ret = xen_map_shared_info(info);
51 	if (ret) {
52 		LOG_ERR("%s: failed to map for Xen shared page, ret = %d\n",
53 			__func__, ret);
54 		return ret;
55 	}
56 
57 	/* Set value for globally visible pointer */
58 	HYPERVISOR_shared_info = info;
59 
60 	ret = xen_events_init();
61 	if (ret) {
62 		LOG_ERR("%s: failed init Xen event channels, ret = %d\n",
63 			__func__, ret);
64 		return ret;
65 	}
66 
67 	return 0;
68 }
69 
70 SYS_INIT(xen_enlighten_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
71