blob: 4660f3fff20d8f313aec40be183fa0e000727e61 [file] [log] [blame]
Andrii Anisov355d1e42020-08-06 12:42:47 +03001// 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>
Oleksandr Andrushchenko10fa5362020-08-06 12:43:00 +030015#include <xen.h>
Andrii Anisov355d1e42020-08-06 12:42:47 +030016
17#include <asm/io.h>
18#include <asm/armv8/mmu.h>
19#include <asm/xen.h>
20#include <asm/xen/hypercall.h>
Peng Fan8162f8f2020-08-06 12:42:50 +030021#include <asm/xen/system.h>
Andrii Anisov355d1e42020-08-06 12:42:47 +030022
23#include <linux/compiler.h>
24
Oleksandr Andrushchenko3cc1dcc2020-08-06 12:42:54 +030025#include <xen/gnttab.h>
Peng Fan8162f8f2020-08-06 12:42:50 +030026#include <xen/hvm.h>
27
Andrii Anisov355d1e42020-08-06 12:42:47 +030028DECLARE_GLOBAL_DATA_PTR;
29
30int 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 */
41void *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
49static struct mm_region xen_mem_map[MAX_MEM_MAP_REGIONS];
50struct mm_region *mem_map = xen_mem_map;
51
52static 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
62static int setup_mem_map(void)
63{
Peng Fan8162f8f2020-08-06 12:42:50 +030064 int i = 0, ret, mem, reg = 0;
Andrii Anisov355d1e42020-08-06 12:42:47 +030065 struct fdt_resource res;
66 const void *blob = gd->fdt_blob;
Peng Fan8162f8f2020-08-06 12:42:50 +030067 u64 gfn;
Oleksandr Andrushchenko3cc1dcc2020-08-06 12:42:54 +030068 phys_addr_t gnttab_base;
69 phys_size_t gnttab_sz;
Peng Fan8162f8f2020-08-06 12:42:50 +030070
71 /*
72 * Add "magic" region which is used by Xen to provide some essentials
Oleksandr Andrushchenko4b728452020-08-06 12:42:53 +030073 * for the guest: we need console and xenstore.
Peng Fan8162f8f2020-08-06 12:42:50 +030074 */
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++;
Andrii Anisov355d1e42020-08-06 12:42:47 +030088
Oleksandr Andrushchenko4b728452020-08-06 12:42:53 +030089 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
Oleksandr Andrushchenko3cc1dcc2020-08-06 12:42:54 +0300103 /* 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
Andrii Anisov355d1e42020-08-06 12:42:47 +0300113 mem = get_next_memory_node(blob, -1);
114 if (mem < 0) {
115 printf("%s: Missing /memory node\n", __func__);
116 return -EINVAL;
117 }
118
Peng Fan8162f8f2020-08-06 12:42:50 +0300119 for (; i < MAX_MEM_MAP_REGIONS; i++) {
Andrii Anisov355d1e42020-08-06 12:42:47 +0300120 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
145void 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. */
154int 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
165int dram_init_banksize(void)
166{
167 return fdtdec_setup_memory_banksize();
168}
169
170/*
171 * Board specific reset that is system reset.
172 */
173void reset_cpu(ulong addr)
174{
175}
176
177int ft_system_setup(void *blob, struct bd_info *bd)
178{
179 return 0;
180}
181
182int ft_board_setup(void *blob, struct bd_info *bd)
183{
184 return 0;
185}
186
Andrii Anisov355d1e42020-08-06 12:42:47 +0300187int print_cpuinfo(void)
188{
189 printf("Xen virtual CPU\n");
190 return 0;
191}
192
Oleksandr Andrushchenko10fa5362020-08-06 12:43:00 +0300193void board_cleanup_before_linux(void)
194{
195 xen_fini();
196}
197