ia64/xen-unstable

view xen/arch/ia64/xen/dom_fw_dom0.c @ 15561:e487cc249171

[IA64] Pass the bare LSAPIC ID to dom0

This patch fixes an issue which dom0 cannot boot with dom0_max_vcpus.
Currently LSAPIC IDs are create by xen, but ACPI SRAT table is the bare
table. So on some boxes node_cpuid[].phys_id are different from
cpu_physical_id()s, and we cannot boot dom0.

Instead, pass the bare LSAPIC ID to dom0.

Signed-off-by: Akio Takebe <takebe_akio@jp.fujitsu.com>
author Alex Williamson <alex.williamson@hp.com>
date Thu Jul 19 15:56:53 2007 -0600 (2007-07-19)
parents c0cdcebc0377
children fcdd56b88acd
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 */
21 /*
22 * Xen domain firmware emulation support
23 * Copyright (C) 2004 Hewlett-Packard Co.
24 * Dan Magenheimer (dan.magenheimer@hp.com)
25 */
27 #include <xen/config.h>
28 #include <xen/acpi.h>
29 #include <xen/errno.h>
30 #include <xen/sched.h>
32 #include <asm/dom_fw.h>
33 #include <asm/dom_fw_common.h>
34 #include <asm/dom_fw_dom0.h>
35 #include <asm/dom_fw_utils.h>
37 #include <linux/sort.h>
39 static u32 lsapic_nbr;
41 /* Modify lsapic table. Provides LPs. */
42 static int __init
43 acpi_update_lsapic(acpi_table_entry_header * header, const unsigned long end)
44 {
45 struct acpi_table_lsapic *lsapic;
46 int enable;
48 lsapic = (struct acpi_table_lsapic *)header;
49 if (!lsapic)
50 return -EINVAL;
52 if (lsapic_nbr < MAX_VIRT_CPUS && dom0->vcpu[lsapic_nbr] != NULL)
53 enable = 1;
54 else
55 enable = 0;
57 if (lsapic->flags.enabled && enable) {
58 if (lsapic->id == 0) {
59 lsapic->id = lsapic_nbr;
60 lsapic->eid = 0;
61 }
62 lsapic_nbr++;
63 printk("enable lsapic entry: 0x%lx (id:eid=%x:%x)\n",
64 (u64)lsapic, lsapic->id, lsapic->eid);
65 } else if (lsapic->flags.enabled) {
66 printk("DISABLE lsapic entry: 0x%lx (id:eid=%x:%x)\n",
67 (u64)lsapic, lsapic->id, lsapic->eid);
68 lsapic->flags.enabled = 0;
69 lsapic->id = 0;
70 lsapic->eid = 0;
71 }
72 return 0;
73 }
75 static int __init
76 acpi_patch_plat_int_src(acpi_table_entry_header * header,
77 const unsigned long end)
78 {
79 struct acpi_table_plat_int_src *plintsrc;
81 plintsrc = (struct acpi_table_plat_int_src *)header;
82 if (!plintsrc)
83 return -EINVAL;
85 if (plintsrc->type == ACPI_INTERRUPT_CPEI) {
86 printk("ACPI_INTERRUPT_CPEI disabled for Domain0\n");
87 plintsrc->type = -1;
88 }
89 return 0;
90 }
92 static int __init
93 acpi_update_madt_checksum(unsigned long phys_addr, unsigned long size)
94 {
95 struct acpi_table_madt *acpi_madt;
97 if (!phys_addr || !size)
98 return -EINVAL;
100 acpi_madt = (struct acpi_table_madt *)__va(phys_addr);
101 acpi_madt->header.checksum = 0;
102 acpi_madt->header.checksum = generate_acpi_checksum(acpi_madt, size);
104 return 0;
105 }
107 /* base is physical address of acpi table */
108 static void __init touch_acpi_table(void)
109 {
110 lsapic_nbr = 0;
112 if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_update_lsapic, 0) < 0)
113 printk("Error parsing MADT - no LAPIC entries\n");
114 if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC,
115 acpi_patch_plat_int_src, 0) < 0)
116 printk("Error parsing MADT - no PLAT_INT_SRC entries\n");
118 acpi_table_parse(ACPI_APIC, acpi_update_madt_checksum);
120 return;
121 }
123 void __init efi_systable_init_dom0(struct fw_tables *tables)
124 {
125 int i = 1;
127 /* Write messages to the console. */
128 touch_acpi_table();
130 printk("Domain0 EFI passthrough:");
131 if (efi.mps) {
132 tables->efi_tables[i].guid = MPS_TABLE_GUID;
133 tables->efi_tables[i].table = __pa(efi.mps);
134 printk(" MPS=0x%lx", tables->efi_tables[i].table);
135 i++;
136 }
137 if (efi.acpi20) {
138 tables->efi_tables[i].guid = ACPI_20_TABLE_GUID;
139 tables->efi_tables[i].table = __pa(efi.acpi20);
140 printk(" ACPI 2.0=0x%lx", tables->efi_tables[i].table);
141 i++;
142 }
143 if (efi.acpi) {
144 tables->efi_tables[i].guid = ACPI_TABLE_GUID;
145 tables->efi_tables[i].table = __pa(efi.acpi);
146 printk(" ACPI=0x%lx", tables->efi_tables[i].table);
147 i++;
148 }
149 if (efi.smbios) {
150 tables->efi_tables[i].guid = SMBIOS_TABLE_GUID;
151 tables->efi_tables[i].table = __pa(efi.smbios);
152 printk(" SMBIOS=0x%lx", tables->efi_tables[i].table);
153 i++;
154 }
155 if (efi.hcdp) {
156 tables->efi_tables[i].guid = HCDP_TABLE_GUID;
157 tables->efi_tables[i].table = __pa(efi.hcdp);
158 printk(" HCDP=0x%lx", tables->efi_tables[i].table);
159 i++;
160 }
161 printk("\n");
162 BUG_ON(i > NUM_EFI_SYS_TABLES);
163 }
165 static void __init
166 setup_dom0_memmap_info(struct domain *d, struct fw_tables *tables)
167 {
168 int i;
169 size_t size;
170 unsigned int num_pages;
171 efi_memory_desc_t *md;
172 efi_memory_desc_t *last_mem_md = NULL;
173 xen_ia64_memmap_info_t *memmap_info;
174 unsigned long paddr_start;
175 unsigned long paddr_end;
177 size = sizeof(*memmap_info) +
178 (tables->num_mds + 1) * sizeof(tables->efi_memmap[0]);
179 num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
180 for (i = tables->num_mds - 1; i >= 0; i--) {
181 md = &tables->efi_memmap[i];
182 if (md->attribute == EFI_MEMORY_WB &&
183 md->type == EFI_CONVENTIONAL_MEMORY &&
184 md->num_pages >
185 ((num_pages + 1) << (PAGE_SHIFT - EFI_PAGE_SHIFT))) {
186 last_mem_md = md;
187 break;
188 }
189 }
191 if (last_mem_md == NULL) {
192 printk("%s: warning: "
193 "no dom0 contiguous memory to hold memory map\n",
194 __func__);
195 return;
196 }
197 paddr_end = last_mem_md->phys_addr +
198 (last_mem_md->num_pages << EFI_PAGE_SHIFT);
199 paddr_start = (paddr_end - (num_pages << PAGE_SHIFT)) & PAGE_MASK;
200 last_mem_md->num_pages -= (paddr_end - paddr_start) >> EFI_PAGE_SHIFT;
202 md = &tables->efi_memmap[tables->num_mds];
203 tables->num_mds++;
204 md->type = EFI_RUNTIME_SERVICES_DATA;
205 md->phys_addr = paddr_start;
206 md->virt_addr = 0;
207 md->num_pages = num_pages << (PAGE_SHIFT - EFI_PAGE_SHIFT);
208 md->attribute = EFI_MEMORY_WB;
210 BUG_ON(tables->fw_tables_size <
211 sizeof(*tables) +
212 sizeof(tables->efi_memmap[0]) * tables->num_mds);
213 /* with this sort, md doesn't point memmap table */
214 sort(tables->efi_memmap, tables->num_mds,
215 sizeof(efi_memory_desc_t), efi_mdt_cmp, NULL);
217 memmap_info = domain_mpa_to_imva(d, paddr_start);
218 memmap_info->efi_memdesc_size = sizeof(md[0]);
219 memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
220 memmap_info->efi_memmap_size = tables->num_mds * sizeof(md[0]);
221 dom_fw_copy_to(d,
222 paddr_start + offsetof(xen_ia64_memmap_info_t, memdesc),
223 &tables->efi_memmap[0], memmap_info->efi_memmap_size);
224 d->shared_info->arch.memmap_info_num_pages = num_pages;
225 d->shared_info->arch.memmap_info_pfn = paddr_start >> PAGE_SHIFT;
226 }
228 /* setup_guest() @ libxc/xc_linux_build() arranges memory for domU.
229 * however no one arranges memory for dom0,
230 * instead we allocate pages manually.
231 */
232 static void
233 assign_new_domain0_range(struct domain *d, const efi_memory_desc_t * md)
234 {
235 if (md->type == EFI_PAL_CODE ||
236 md->type == EFI_RUNTIME_SERVICES_DATA ||
237 md->type == EFI_CONVENTIONAL_MEMORY) {
238 unsigned long start = md->phys_addr & PAGE_MASK;
239 unsigned long end =
240 md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
241 unsigned long addr;
243 if (end == start) {
244 /* md->num_pages = 0 is allowed. */
245 return;
246 }
248 for (addr = start; addr < end; addr += PAGE_SIZE)
249 assign_new_domain0_page(d, addr);
250 }
251 }
253 /* Complete the dom0 memmap. */
254 int __init
255 complete_dom0_memmap(struct domain *d, struct fw_tables *tables)
256 {
257 u64 addr;
258 void *efi_map_start, *efi_map_end, *p;
259 u64 efi_desc_size;
260 int i;
262 for (i = 0; i < tables->num_mds; i++)
263 assign_new_domain0_range(d, &tables->efi_memmap[i]);
265 /* Walk through all MDT entries.
266 Copy all interesting entries. */
267 efi_map_start = __va(ia64_boot_param->efi_memmap);
268 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
269 efi_desc_size = ia64_boot_param->efi_memdesc_size;
271 for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
272 const efi_memory_desc_t *md = p;
273 efi_memory_desc_t *dom_md = &tables->efi_memmap[tables->num_mds];
274 u64 start = md->phys_addr;
275 u64 size = md->num_pages << EFI_PAGE_SHIFT;
276 u64 end = start + size;
277 u64 mpaddr;
278 unsigned long flags;
280 switch (md->type) {
281 case EFI_RUNTIME_SERVICES_CODE:
282 case EFI_RUNTIME_SERVICES_DATA:
283 case EFI_ACPI_RECLAIM_MEMORY:
284 case EFI_ACPI_MEMORY_NVS:
285 case EFI_RESERVED_TYPE:
286 /*
287 * Map into dom0 - We must respect protection
288 * and cache attributes. Not all of these pages
289 * are writable!!!
290 */
291 flags = ASSIGN_writable; /* dummy - zero */
292 if (md->attribute & EFI_MEMORY_WP)
293 flags |= ASSIGN_readonly;
294 if ((md->attribute & EFI_MEMORY_UC) &&
295 !(md->attribute & EFI_MEMORY_WB))
296 flags |= ASSIGN_nocache;
298 assign_domain_mach_page(d, start, size, flags);
300 /* Fall-through. */
301 case EFI_MEMORY_MAPPED_IO:
302 /* Will be mapped with ioremap. */
303 /* Copy descriptor. */
304 *dom_md = *md;
305 dom_md->virt_addr = 0;
306 tables->num_mds++;
307 break;
309 case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
310 flags = ASSIGN_writable; /* dummy - zero */
311 if (md->attribute & EFI_MEMORY_UC)
312 flags |= ASSIGN_nocache;
314 if (start > 0x1ffffffff0000000UL) {
315 mpaddr = 0x4000000000000UL - size;
316 printk(XENLOG_INFO "Remapping IO ports from "
317 "%lx to %lx\n", start, mpaddr);
318 } else
319 mpaddr = start;
321 /* Map into dom0. */
322 assign_domain_mmio_page(d, mpaddr, start, size, flags);
323 /* Copy descriptor. */
324 *dom_md = *md;
325 dom_md->phys_addr = mpaddr;
326 dom_md->virt_addr = 0;
327 tables->num_mds++;
328 break;
330 case EFI_CONVENTIONAL_MEMORY:
331 case EFI_LOADER_CODE:
332 case EFI_LOADER_DATA:
333 case EFI_BOOT_SERVICES_CODE:
334 case EFI_BOOT_SERVICES_DATA: {
335 u64 dom_md_start;
336 u64 dom_md_end;
337 unsigned long left_mem =
338 (unsigned long)(d->max_pages - d->tot_pages) <<
339 PAGE_SHIFT;
341 if (!(md->attribute & EFI_MEMORY_WB))
342 break;
344 dom_md_start = max(tables->fw_end_paddr, start);
345 dom_md_end = dom_md_start;
346 do {
347 dom_md_end = min(dom_md_end + left_mem, end);
348 if (dom_md_end < dom_md_start + PAGE_SIZE)
349 break;
351 dom_md->type = EFI_CONVENTIONAL_MEMORY;
352 dom_md->phys_addr = dom_md_start;
353 dom_md->virt_addr = 0;
354 dom_md->num_pages =
355 (dom_md_end - dom_md_start) >>
356 EFI_PAGE_SHIFT;
357 dom_md->attribute = EFI_MEMORY_WB;
359 assign_new_domain0_range(d, dom_md);
360 /*
361 * recalculate left_mem.
362 * we might already allocated memory in
363 * this region because of kernel loader.
364 * So we might consumed less than
365 * (dom_md_end - dom_md_start) above.
366 */
367 left_mem = (unsigned long)
368 (d->max_pages - d->tot_pages) <<
369 PAGE_SHIFT;
370 } while (left_mem > 0 && dom_md_end < end);
372 if (!(dom_md_end < dom_md_start + PAGE_SIZE))
373 tables->num_mds++;
374 break;
375 }
377 case EFI_UNUSABLE_MEMORY:
378 case EFI_PAL_CODE:
379 /*
380 * We don't really need these, but holes in the
381 * memory map may cause Linux to assume there are
382 * uncacheable ranges within a granule.
383 */
384 dom_md->type = EFI_UNUSABLE_MEMORY;
385 dom_md->phys_addr = start;
386 dom_md->virt_addr = 0;
387 dom_md->num_pages = (end - start) >> EFI_PAGE_SHIFT;
388 dom_md->attribute = EFI_MEMORY_WB;
389 tables->num_mds++;
390 break;
392 default:
393 /* Print a warning but continue. */
394 printk("complete_dom0_memmap: warning: "
395 "unhandled MDT entry type %u\n", md->type);
396 }
397 }
398 BUG_ON(tables->fw_tables_size <
399 sizeof(*tables) +
400 sizeof(tables->efi_memmap[0]) * tables->num_mds);
402 sort(tables->efi_memmap, tables->num_mds, sizeof(efi_memory_desc_t),
403 efi_mdt_cmp, NULL);
405 // Map low-memory holes & unmapped MMIO for legacy drivers
406 for (addr = 0; addr < ONE_MB; addr += PAGE_SIZE) {
407 if (domain_page_mapped(d, addr))
408 continue;
410 if (efi_mmio(addr, PAGE_SIZE)) {
411 unsigned long flags;
412 flags = ASSIGN_writable | ASSIGN_nocache;
413 assign_domain_mmio_page(d, addr, addr, PAGE_SIZE,
414 flags);
415 }
416 }
417 setup_dom0_memmap_info(d, tables);
418 return tables->num_mds;
419 }
421 /*
422 * Local variables:
423 * mode: C
424 * c-set-style: "linux"
425 * c-basic-offset: 8
426 * tab-width: 8
427 * indent-tabs-mode: t
428 * End:
429 */