Merge tag 'u-boot-imx-20200825' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
[platform/kernel/u-boot.git] / board / xen / xenguest_arm64 / xenguest_arm64.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) 2013
4  * David Feng <fenghua@phytium.com.cn>
5  * Sharma Bhupesh <bhupesh.sharma@freescale.com>
6  *
7  * (C) 2020 EPAM Systems Inc
8  */
9
10 #include <common.h>
11 #include <cpu_func.h>
12 #include <dm.h>
13 #include <errno.h>
14 #include <malloc.h>
15 #include <xen.h>
16
17 #include <asm/io.h>
18 #include <asm/armv8/mmu.h>
19 #include <asm/xen.h>
20 #include <asm/xen/hypercall.h>
21 #include <asm/xen/system.h>
22
23 #include <linux/compiler.h>
24
25 #include <xen/gnttab.h>
26 #include <xen/hvm.h>
27
28 DECLARE_GLOBAL_DATA_PTR;
29
30 int board_init(void)
31 {
32         return 0;
33 }
34
35 /*
36  * Use fdt provided by Xen: according to
37  * https://www.kernel.org/doc/Documentation/arm64/booting.txt
38  * x0 is the physical address of the device tree blob (dtb) in system RAM.
39  * This is stored in rom_pointer during low level init.
40  */
41 void *board_fdt_blob_setup(void)
42 {
43         if (fdt_magic(rom_pointer[0]) != FDT_MAGIC)
44                 return NULL;
45         return (void *)rom_pointer[0];
46 }
47
48 #define MAX_MEM_MAP_REGIONS 5
49 static struct mm_region xen_mem_map[MAX_MEM_MAP_REGIONS];
50 struct mm_region *mem_map = xen_mem_map;
51
52 static int get_next_memory_node(const void *blob, int mem)
53 {
54         do {
55                 mem = fdt_node_offset_by_prop_value(blob, mem,
56                                                     "device_type", "memory", 7);
57         } while (!fdtdec_get_is_enabled(blob, mem));
58
59         return mem;
60 }
61
62 static int setup_mem_map(void)
63 {
64         int i = 0, ret, mem, reg = 0;
65         struct fdt_resource res;
66         const void *blob = gd->fdt_blob;
67         u64 gfn;
68         phys_addr_t gnttab_base;
69         phys_size_t gnttab_sz;
70
71         /*
72          * Add "magic" region which is used by Xen to provide some essentials
73          * for the guest: we need console and xenstore.
74          */
75         ret = hvm_get_parameter_maintain_dcache(HVM_PARAM_CONSOLE_PFN, &gfn);
76         if (ret < 0) {
77                 printf("%s: Can't get HVM_PARAM_CONSOLE_PFN, ret %d\n",
78                        __func__, ret);
79                 return -EINVAL;
80         }
81
82         xen_mem_map[i].virt = PFN_PHYS(gfn);
83         xen_mem_map[i].phys = PFN_PHYS(gfn);
84         xen_mem_map[i].size = PAGE_SIZE;
85         xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
86                                 PTE_BLOCK_INNER_SHARE);
87         i++;
88
89         ret = hvm_get_parameter_maintain_dcache(HVM_PARAM_STORE_PFN, &gfn);
90         if (ret < 0) {
91                 printf("%s: Can't get HVM_PARAM_STORE_PFN, ret %d\n",
92                        __func__, ret);
93                 return -EINVAL;
94         }
95
96         xen_mem_map[i].virt = PFN_PHYS(gfn);
97         xen_mem_map[i].phys = PFN_PHYS(gfn);
98         xen_mem_map[i].size = PAGE_SIZE;
99         xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
100                                 PTE_BLOCK_INNER_SHARE);
101         i++;
102
103         /* Get Xen's suggested physical page assignments for the grant table. */
104         get_gnttab_base(&gnttab_base, &gnttab_sz);
105
106         xen_mem_map[i].virt = gnttab_base;
107         xen_mem_map[i].phys = gnttab_base;
108         xen_mem_map[i].size = gnttab_sz;
109         xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
110                                 PTE_BLOCK_INNER_SHARE);
111         i++;
112
113         mem = get_next_memory_node(blob, -1);
114         if (mem < 0) {
115                 printf("%s: Missing /memory node\n", __func__);
116                 return -EINVAL;
117         }
118
119         for (; i < MAX_MEM_MAP_REGIONS; i++) {
120                 ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
121                 if (ret == -FDT_ERR_NOTFOUND) {
122                         reg = 0;
123                         mem = get_next_memory_node(blob, mem);
124                         if (mem == -FDT_ERR_NOTFOUND)
125                                 break;
126
127                         ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
128                         if (ret == -FDT_ERR_NOTFOUND)
129                                 break;
130                 }
131                 if (ret != 0) {
132                         printf("No reg property for memory node\n");
133                         return -EINVAL;
134                 }
135
136                 xen_mem_map[i].virt = (phys_addr_t)res.start;
137                 xen_mem_map[i].phys = (phys_addr_t)res.start;
138                 xen_mem_map[i].size = (phys_size_t)(res.end - res.start + 1);
139                 xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
140                                         PTE_BLOCK_INNER_SHARE);
141         }
142         return 0;
143 }
144
145 void enable_caches(void)
146 {
147         /* Re-setup the memory map as BSS gets cleared after relocation. */
148         setup_mem_map();
149         icache_enable();
150         dcache_enable();
151 }
152
153 /* Read memory settings from the Xen provided device tree. */
154 int dram_init(void)
155 {
156         int ret;
157
158         ret = fdtdec_setup_mem_size_base();
159         if (ret < 0)
160                 return ret;
161         /* Setup memory map, so MMU page table size can be estimated. */
162         return setup_mem_map();
163 }
164
165 int dram_init_banksize(void)
166 {
167         return fdtdec_setup_memory_banksize();
168 }
169
170 /*
171  * Board specific reset that is system reset.
172  */
173 void reset_cpu(ulong addr)
174 {
175 }
176
177 int ft_system_setup(void *blob, struct bd_info *bd)
178 {
179         return 0;
180 }
181
182 int ft_board_setup(void *blob, struct bd_info *bd)
183 {
184         return 0;
185 }
186
187 int print_cpuinfo(void)
188 {
189         printf("Xen virtual CPU\n");
190         return 0;
191 }
192
193 void board_cleanup_before_linux(void)
194 {
195         xen_fini();
196 }
197