1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <xen/sched.h>
4 #include <xen/static-memory.h>
5
6 #include <asm/setup.h>
7
append_static_memory_to_bank(struct domain * d,struct membank * bank,mfn_t smfn,paddr_t size)8 static bool __init append_static_memory_to_bank(struct domain *d,
9 struct membank *bank,
10 mfn_t smfn,
11 paddr_t size)
12 {
13 int res;
14 unsigned int nr_pages = PFN_DOWN(size);
15 gfn_t sgfn;
16
17 /*
18 * For direct-mapped domain, the GFN match the MFN.
19 * Otherwise, this is inferred on what has already been allocated
20 * in the bank.
21 */
22 if ( !is_domain_direct_mapped(d) )
23 sgfn = gaddr_to_gfn(bank->start + bank->size);
24 else
25 sgfn = gaddr_to_gfn(mfn_to_maddr(smfn));
26
27 res = guest_physmap_add_pages(d, sgfn, smfn, nr_pages);
28 if ( res )
29 {
30 dprintk(XENLOG_ERR, "Failed to map pages to DOMU: %d", res);
31 return false;
32 }
33
34 bank->size = bank->size + size;
35
36 return true;
37 }
38
acquire_static_memory_bank(struct domain * d,const __be32 ** cell,u32 addr_cells,u32 size_cells,paddr_t * pbase,paddr_t * psize)39 static mfn_t __init acquire_static_memory_bank(struct domain *d,
40 const __be32 **cell,
41 u32 addr_cells, u32 size_cells,
42 paddr_t *pbase, paddr_t *psize)
43 {
44 mfn_t smfn;
45 int res;
46
47 device_tree_get_reg(cell, addr_cells, size_cells, pbase, psize);
48 ASSERT(IS_ALIGNED(*pbase, PAGE_SIZE) && IS_ALIGNED(*psize, PAGE_SIZE));
49 if ( PFN_DOWN(*psize) > UINT_MAX )
50 {
51 printk(XENLOG_ERR "%pd: static memory size too large: %#"PRIpaddr,
52 d, *psize);
53 return INVALID_MFN;
54 }
55
56 smfn = maddr_to_mfn(*pbase);
57 res = acquire_domstatic_pages(d, smfn, PFN_DOWN(*psize), 0);
58 if ( res )
59 {
60 printk(XENLOG_ERR
61 "%pd: failed to acquire static memory: %d.\n", d, res);
62 return INVALID_MFN;
63 }
64
65 return smfn;
66 }
67
parse_static_mem_prop(const struct dt_device_node * node,u32 * addr_cells,u32 * size_cells,int * length,const __be32 ** cell)68 static int __init parse_static_mem_prop(const struct dt_device_node *node,
69 u32 *addr_cells, u32 *size_cells,
70 int *length, const __be32 **cell)
71 {
72 const struct dt_property *prop;
73
74 prop = dt_find_property(node, "xen,static-mem", NULL);
75
76 *addr_cells = dt_n_addr_cells(node);
77 *size_cells = dt_n_size_cells(node);
78
79 *cell = (const __be32 *)prop->value;
80 *length = prop->length;
81
82 return 0;
83 }
84
85 /* Allocate memory from static memory as RAM for one specific domain d. */
allocate_static_memory(struct domain * d,struct kernel_info * kinfo,const struct dt_device_node * node)86 void __init allocate_static_memory(struct domain *d, struct kernel_info *kinfo,
87 const struct dt_device_node *node)
88 {
89 struct membanks *mem = kernel_info_get_mem(kinfo);
90 u32 addr_cells, size_cells, reg_cells;
91 unsigned int nr_banks, gbank, bank = 0;
92 const uint64_t rambase[] = GUEST_RAM_BANK_BASES;
93 const uint64_t ramsize[] = GUEST_RAM_BANK_SIZES;
94 const __be32 *cell;
95 u64 tot_size = 0;
96 paddr_t pbase, psize, gsize;
97 mfn_t smfn;
98 int length;
99
100 if ( parse_static_mem_prop(node, &addr_cells, &size_cells, &length, &cell) )
101 goto fail;
102 reg_cells = addr_cells + size_cells;
103
104 /*
105 * The static memory will be mapped in the guest at the usual guest memory
106 * addresses (GUEST_RAM0_BASE, GUEST_RAM1_BASE) defined by
107 * xen/include/public/arch-arm.h.
108 */
109 gbank = 0;
110 gsize = ramsize[gbank];
111 mem->bank[gbank].start = rambase[gbank];
112 nr_banks = length / (reg_cells * sizeof (u32));
113
114 for ( ; bank < nr_banks; bank++ )
115 {
116 smfn = acquire_static_memory_bank(d, &cell, addr_cells, size_cells,
117 &pbase, &psize);
118 if ( mfn_eq(smfn, INVALID_MFN) )
119 goto fail;
120
121 printk(XENLOG_INFO "%pd: STATIC BANK[%u] %#"PRIpaddr"-%#"PRIpaddr"\n",
122 d, bank, pbase, pbase + psize);
123
124 while ( 1 )
125 {
126 /* Map as much as possible the static range to the guest bank */
127 if ( !append_static_memory_to_bank(d, &mem->bank[gbank], smfn,
128 min(psize, gsize)) )
129 goto fail;
130
131 /*
132 * The current physical bank is fully mapped.
133 * Handle the next physical bank.
134 */
135 if ( gsize >= psize )
136 {
137 gsize = gsize - psize;
138 break;
139 }
140 /*
141 * When current guest bank is not enough to map, exhaust
142 * the current one and seek to the next.
143 * Before seeking to the next, check if we still have available
144 * guest bank.
145 */
146 else if ( (gbank + 1) >= GUEST_RAM_BANKS )
147 {
148 printk(XENLOG_ERR "Exhausted all possible guest banks.\n");
149 goto fail;
150 }
151 else
152 {
153 psize = psize - gsize;
154 smfn = mfn_add(smfn, gsize >> PAGE_SHIFT);
155 /* Update to the next guest bank. */
156 gbank++;
157 gsize = ramsize[gbank];
158 mem->bank[gbank].start = rambase[gbank];
159 }
160 }
161
162 tot_size += psize;
163 }
164
165 mem->nr_banks = ++gbank;
166
167 kinfo->unassigned_mem -= tot_size;
168 /*
169 * The property 'memory' should match the amount of memory given to the
170 * guest.
171 * Currently, it is only possible to either acquire static memory or let
172 * Xen allocate. *Mixing* is not supported.
173 */
174 if ( kinfo->unassigned_mem )
175 {
176 printk(XENLOG_ERR
177 "Size of \"memory\" property doesn't match up with the sum-up of \"xen,static-mem\". Unsupported configuration.\n");
178 goto fail;
179 }
180
181 return;
182
183 fail:
184 panic("Failed to allocate requested static memory for domain %pd.\n", d);
185 }
186
187 /*
188 * Allocate static memory as RAM for one specific domain d.
189 * The static memory will be directly mapped in the guest(Guest Physical
190 * Address == Physical Address).
191 */
assign_static_memory_11(struct domain * d,struct kernel_info * kinfo,const struct dt_device_node * node)192 void __init assign_static_memory_11(struct domain *d, struct kernel_info *kinfo,
193 const struct dt_device_node *node)
194 {
195 struct membanks *mem = kernel_info_get_mem(kinfo);
196 u32 addr_cells, size_cells, reg_cells;
197 unsigned int nr_banks, bank = 0;
198 const __be32 *cell;
199 paddr_t pbase, psize;
200 mfn_t smfn;
201 int length;
202
203 if ( parse_static_mem_prop(node, &addr_cells, &size_cells, &length, &cell) )
204 {
205 printk(XENLOG_ERR
206 "%pd: failed to parse \"xen,static-mem\" property.\n", d);
207 goto fail;
208 }
209 reg_cells = addr_cells + size_cells;
210 nr_banks = length / (reg_cells * sizeof(u32));
211
212 if ( nr_banks > mem->max_banks )
213 {
214 printk(XENLOG_ERR
215 "%pd: exceed max number of supported guest memory banks.\n", d);
216 goto fail;
217 }
218
219 for ( ; bank < nr_banks; bank++ )
220 {
221 smfn = acquire_static_memory_bank(d, &cell, addr_cells, size_cells,
222 &pbase, &psize);
223 if ( mfn_eq(smfn, INVALID_MFN) )
224 goto fail;
225
226 printk(XENLOG_INFO "%pd: STATIC BANK[%u] %#"PRIpaddr"-%#"PRIpaddr"\n",
227 d, bank, pbase, pbase + psize);
228
229 /* One guest memory bank is matched with one physical memory bank. */
230 mem->bank[bank].start = pbase;
231 if ( !append_static_memory_to_bank(d, &mem->bank[bank],
232 smfn, psize) )
233 goto fail;
234
235 kinfo->unassigned_mem -= psize;
236 }
237
238 mem->nr_banks = nr_banks;
239
240 /*
241 * The property 'memory' should match the amount of memory given to
242 * the guest.
243 * Currently, it is only possible to either acquire static memory or
244 * let Xen allocate. *Mixing* is not supported.
245 */
246 if ( kinfo->unassigned_mem != 0 )
247 {
248 printk(XENLOG_ERR
249 "Size of \"memory\" property doesn't match up with the sum-up of \"xen,static-mem\".\n");
250 goto fail;
251 }
252
253 return;
254
255 fail:
256 panic("Failed to assign requested static memory for direct-map domain %pd.\n",
257 d);
258 }
259
260 /* Static memory initialization */
init_staticmem_pages(void)261 void __init init_staticmem_pages(void)
262 {
263 const struct membanks *reserved_mem = bootinfo_get_reserved_mem();
264 unsigned int bank;
265
266 for ( bank = 0 ; bank < reserved_mem->nr_banks; bank++ )
267 {
268 if ( reserved_mem->bank[bank].type == MEMBANK_STATIC_DOMAIN )
269 init_staticmem_bank(&reserved_mem->bank[bank]);
270 }
271 }
272
273 /*
274 * Local variables:
275 * mode: C
276 * c-file-style: "BSD"
277 * c-basic-offset: 4
278 * tab-width: 4
279 * indent-tabs-mode: nil
280 * End:
281 */
282