ia64/xen-unstable

view xen/arch/ia64/xen/dom_fw_utils.c @ 15423:cbf749e9961f

[IA64] Cleanup: Move is_platform_hp_ski() from xenmisc.c to xensetup.c

- only caller is start_kernel
- change to static __init
- also move running_on_sim to xensetup.c, and change it from unsigned
long to int, since it's just a boolean
- declare running_on_sim in config.h near some other externs

Tested by building, booting, starting a PV guest on rx2620.

Signed-off-by: Aron Griffis <aron@hp.com>
author Alex Williamson <alex.williamson@hp.com>
date Mon Jul 02 10:25:29 2007 -0600 (2007-07-02)
parents 7d4c40c21690
children ba98732b44c7
line source
1 /******************************************************************************
2 *
3 * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
4 * VA Linux Systems Japan K.K.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
22 #include <xen/types.h>
23 #include <xen/version.h>
24 #include <xen/errno.h>
25 #include <xen/sched.h>
27 #include <asm/fpswa.h>
28 #include <asm/dom_fw.h>
29 #include <asm/dom_fw_common.h>
30 #include <asm/dom_fw_utils.h>
32 #include <linux/sort.h>
34 uint32_t xen_ia64_version(struct domain *unused)
35 {
36 return (xen_major_version() << 16) | xen_minor_version();
37 }
39 int xen_ia64_fpswa_revision(struct domain *d, unsigned int *revision)
40 {
41 if (fpswa_interface == NULL)
42 return -ENOSYS;
44 *revision = fpswa_interface->revision;
45 return 0;
46 }
48 int xen_ia64_is_vcpu_allocated(struct domain *d, uint32_t vcpu)
49 {
50 return d->vcpu[vcpu] != NULL;
51 }
53 int xen_ia64_is_running_on_sim(struct domain *unused)
54 {
55 return running_on_sim;
56 }
58 int xen_ia64_is_dom0(struct domain *d)
59 {
60 return d == dom0;
61 }
63 static void dom_fw_domain_init(struct domain *d, struct fw_tables *tables)
64 {
65 /* Initialise for EFI_SET_VIRTUAL_ADDRESS_MAP emulation */
66 d->arch.efi_runtime = &tables->efi_runtime;
67 d->arch.fpswa_inf = &tables->fpswa_inf;
68 d->arch.sal_data = &tables->sal_data;
69 }
71 static int dom_fw_set_convmem_end(struct domain *d)
72 {
73 unsigned long gpaddr;
74 size_t size;
75 xen_ia64_memmap_info_t *memmap_info;
76 efi_memory_desc_t *md;
77 void *p;
78 void *memmap_start;
79 void *memmap_end;
81 if (d->shared_info->arch.memmap_info_pfn == 0)
82 return -EINVAL;
84 gpaddr = d->shared_info->arch.memmap_info_pfn << PAGE_SHIFT;
85 size = d->shared_info->arch.memmap_info_num_pages << PAGE_SHIFT;
86 memmap_info = _xmalloc(size, __alignof__(*memmap_info));
87 if (memmap_info == NULL)
88 return -ENOMEM;
89 dom_fw_copy_from(memmap_info, d, gpaddr, size);
90 if (memmap_info->efi_memmap_size == 0 ||
91 memmap_info->efi_memdesc_size != sizeof(*md) ||
92 memmap_info->efi_memdesc_version != EFI_MEMORY_DESCRIPTOR_VERSION ||
93 sizeof(*memmap_info) + memmap_info->efi_memmap_size > size ||
94 memmap_info->efi_memmap_size / memmap_info->efi_memdesc_size == 0) {
95 xfree(memmap_info);
96 return -EINVAL;
97 }
99 memmap_start = &memmap_info->memdesc;
100 memmap_end = memmap_start + memmap_info->efi_memmap_size;
102 /* sort it bofore use
103 * XXX: this is created by user space domain builder so that
104 * we should check its integrity */
105 sort(&memmap_info->memdesc,
106 memmap_info->efi_memmap_size / memmap_info->efi_memdesc_size,
107 memmap_info->efi_memdesc_size, efi_mdt_cmp, NULL);
109 if (d->arch.convmem_end == 0)
110 d->arch.convmem_end = d->max_pages << PAGE_SHIFT;
112 for (p = memmap_start; p < memmap_end;
113 p += memmap_info->efi_memdesc_size) {
114 unsigned long end;
116 md = p;
117 end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
119 if (md->attribute == EFI_MEMORY_WB &&
120 md->type == EFI_CONVENTIONAL_MEMORY &&
121 md->num_pages > 0 && d->arch.convmem_end < end)
122 d->arch.convmem_end = end;
123 }
125 dom_fw_copy_to(d, gpaddr, memmap_info, size);
126 xfree(memmap_info);
127 return 0;
128 }
130 /* allocate a page for fw
131 * guest_setup() @ libxc/xc_linux_build.c does for domU
132 */
133 static inline void
134 assign_new_domain_page_if_dom0(struct domain *d, unsigned long mpaddr)
135 {
136 if (d == dom0)
137 assign_new_domain0_page(d, mpaddr);
138 }
140 static void dom_fw_setup_for_domain_restore(domain_t * d, unsigned long maxmem)
141 {
142 assign_new_domain_page(d, FW_HYPERCALL_BASE_PADDR);
143 dom_fw_domain_init(d, domain_mpa_to_imva(d, FW_TABLES_BASE_PADDR));
144 d->arch.convmem_end = maxmem;
145 }
147 /* copy memory range to domain pseudo physical address space */
148 void
149 dom_fw_copy_to(struct domain *d, unsigned long dest_gpaddr,
150 void *src, size_t size)
151 {
152 while (size > 0) {
153 unsigned long page_offset = dest_gpaddr & ~PAGE_MASK;
154 size_t copy_size = size;
155 void *dest;
157 if (page_offset + copy_size > PAGE_SIZE)
158 copy_size = PAGE_SIZE - page_offset;
159 dest = domain_mpa_to_imva(d, dest_gpaddr);
160 memcpy(dest, src, copy_size);
162 src += copy_size;
163 dest_gpaddr += copy_size;
164 size -= copy_size;
165 }
166 }
168 /* copy memory range from domain pseudo physical address space */
169 void
170 dom_fw_copy_from(void *dest, struct domain *d, unsigned long src_gpaddr,
171 size_t size)
172 {
173 while (size > 0) {
174 unsigned long page_offset = src_gpaddr & ~PAGE_MASK;
175 size_t copy_size = size;
176 void *src;
178 if (page_offset + copy_size > PAGE_SIZE)
179 copy_size = PAGE_SIZE - page_offset;
180 src = domain_mpa_to_imva(d, src_gpaddr);
181 memcpy(dest, src, copy_size);
183 dest += copy_size;
184 src_gpaddr += copy_size;
185 size -= copy_size;
186 }
187 }
189 int dom_fw_setup(domain_t * d, unsigned long bp_mpa, unsigned long maxmem)
190 {
191 int old_domu_builder = 0;
192 struct xen_ia64_boot_param *bp;
194 BUILD_BUG_ON(sizeof(struct fw_tables) >
195 (FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR));
197 if (bp_mpa == 0) {
198 /* bp_mpa == 0 means this is domain restore case. */
199 dom_fw_setup_for_domain_restore(d, maxmem);
200 return 0;
201 }
203 /* Create page for boot_param. */
204 assign_new_domain_page_if_dom0(d, bp_mpa);
205 bp = domain_mpa_to_imva(d, bp_mpa);
206 if (d != dom0) {
207 /*
208 * XXX kludge.
209 * when XEN_DOMCTL_arch_setup is called, shared_info can't
210 * be accessed by libxc so that memmap_info_pfn isn't
211 * initialized. But dom_fw_set_convmem_end() requires it,
212 * so here we initialize it.
213 * note: domain builder may overwrite memmap_info_num_pages,
214 * memmap_info_pfns later.
215 */
216 if (bp->efi_memmap_size == 0 ||
217 XEN_IA64_MEMMAP_INFO_NUM_PAGES(bp) == 0 ||
218 XEN_IA64_MEMMAP_INFO_PFN(bp) == 0) {
219 /* old domain builder compatibility */
220 d->shared_info->arch.memmap_info_num_pages = 1;
221 d->shared_info->arch.memmap_info_pfn =
222 (maxmem >> PAGE_SHIFT) - 1;
223 old_domu_builder = 1;
224 } else {
225 d->shared_info->arch.memmap_info_num_pages =
226 XEN_IA64_MEMMAP_INFO_NUM_PAGES(bp);
227 d->shared_info->arch.memmap_info_pfn =
228 XEN_IA64_MEMMAP_INFO_PFN(bp);
229 /* currently multi page memmap isn't supported */
230 if (d->shared_info->arch.memmap_info_num_pages != 1)
231 return -ENOSYS;
232 }
233 }
235 /* Create page for acpi tables. */
236 if (d != dom0 && old_domu_builder) {
237 struct fake_acpi_tables *imva;
238 imva = domain_mpa_to_imva(d, FW_ACPI_BASE_PADDR);
239 dom_fw_fake_acpi(d, imva);
240 }
241 if (d == dom0 || old_domu_builder) {
242 int ret;
243 unsigned long imva_hypercall_base;
244 size_t fw_tables_size;
245 struct fw_tables *fw_tables;
246 unsigned long gpaddr;
248 /* Create page for hypercalls. */
249 assign_new_domain_page_if_dom0(d, FW_HYPERCALL_BASE_PADDR);
250 imva_hypercall_base = (unsigned long)domain_mpa_to_imva
251 (d, FW_HYPERCALL_BASE_PADDR);
253 /* Estimate necessary efi memmap size and allocate memory */
254 fw_tables_size = sizeof(*fw_tables) +
255 (ia64_boot_param->efi_memmap_size /
256 ia64_boot_param->efi_memdesc_size + NUM_MEM_DESCS) *
257 sizeof(fw_tables->efi_memmap[0]);
258 if (fw_tables_size <
259 FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR)
260 fw_tables_size =
261 FW_TABLES_END_PADDR_MIN - FW_TABLES_BASE_PADDR;
262 fw_tables_size = (fw_tables_size + ((1UL << EFI_PAGE_SHIFT) - 1))
263 & ~((1UL << EFI_PAGE_SHIFT) - 1);
264 fw_tables =
265 (struct fw_tables *)_xmalloc(fw_tables_size,
266 __alignof__(*fw_tables));
267 if (fw_tables == NULL) {
268 dprintk(XENLOG_INFO,
269 "can't allocate fw_tables memory size = %ld\n",
270 fw_tables_size);
271 return -ENOMEM;
272 }
273 memset(fw_tables, 0, fw_tables_size);
274 BUILD_BUG_ON(FW_END_PADDR_MIN != FW_TABLES_END_PADDR_MIN);
275 fw_tables->fw_tables_size = fw_tables_size;
276 fw_tables->fw_end_paddr = FW_TABLES_BASE_PADDR + fw_tables_size;
277 fw_tables->fw_tables_end_paddr =
278 FW_TABLES_BASE_PADDR + fw_tables_size;
279 fw_tables->num_mds = 0;
281 /* It is necessary to allocate pages before dom_fw_init()
282 * dom_fw_init() uses up page to d->max_pages.
283 */
284 for (gpaddr = FW_TABLES_BASE_PADDR;
285 gpaddr < fw_tables->fw_end_paddr; gpaddr += PAGE_SIZE)
286 assign_new_domain_page_if_dom0(d, gpaddr);
288 ret = dom_fw_init(d, d->arch.breakimm, bp,
289 fw_tables, imva_hypercall_base, maxmem);
290 if (ret < 0) {
291 xfree(fw_tables);
292 return ret;
293 }
295 ret = platform_fw_init(d, bp, fw_tables);
296 if (ret < 0) {
297 xfree(fw_tables);
298 return ret;
299 }
301 if (sizeof(*fw_tables) +
302 fw_tables->num_mds * sizeof(fw_tables->efi_memmap[0]) >
303 fw_tables_size) {
304 panic("EFI memmap too large. Increase NUM_MEM_DESCS.\n"
305 "fw_table_size %ld > %ld num_mds %ld "
306 "NUM_MEM_DESCS %d.\n",
307 fw_tables_size, fw_tables->fw_tables_size,
308 fw_tables->num_mds, NUM_MEM_DESCS);
309 }
310 fw_tables_size = sizeof(*fw_tables) +
311 fw_tables->num_mds * sizeof(fw_tables->efi_memmap[0]);
313 /* clear domain builder internal use member */
314 fw_tables->fw_tables_size = 0;
315 fw_tables->fw_end_paddr = 0;
316 fw_tables->fw_tables_end_paddr = 0;
317 fw_tables->num_mds = 0;
319 /* copy fw_tables into domain pseudo physical address space */
320 dom_fw_copy_to(d, FW_TABLES_BASE_PADDR, fw_tables,
321 fw_tables_size);
322 xfree(fw_tables);
323 }
325 dom_fw_domain_init(d, domain_mpa_to_imva(d, FW_TABLES_BASE_PADDR));
326 return dom_fw_set_convmem_end(d);
327 }
329 /*
330 * Local variables:
331 * mode: C
332 * c-set-style: "linux"
333 * c-basic-offset: 8
334 * tab-width: 8
335 * indent-tabs-mode: t
336 * End:
337 */