~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/arch/ia64/xen/dom_fw_dom0.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 */
 
26
 
 
27
#include <xen/config.h>
 
28
#include <xen/errno.h>
 
29
#include <xen/sched.h>
 
30
#include <xen/list.h>
 
31
#include <xen/acpi.h>
 
32
#include <acpi/actables.h>
 
33
 
 
34
#include <asm/dom_fw.h>
 
35
#include <asm/dom_fw_common.h>
 
36
#include <asm/dom_fw_dom0.h>
 
37
#include <asm/dom_fw_utils.h>
 
38
 
 
39
#include <linux/sort.h>
 
40
 
 
41
struct acpi_backup_table_entry {
 
42
        struct list_head list;
 
43
        unsigned long pa;
 
44
        unsigned long size;
 
45
        unsigned char data[0];
 
46
};
 
47
 
 
48
static LIST_HEAD(acpi_backup_table_list);
 
49
 
 
50
static u32 lsapic_nbr;
 
51
 
 
52
/* Modify lsapic table.  Provides LPs.  */
 
53
static int __init
 
54
acpi_update_lsapic(struct acpi_subtable_header * header, const unsigned long end)
 
55
{
 
56
        struct acpi_table_lsapic *lsapic;
 
57
        int enable;
 
58
 
 
59
        lsapic = (struct acpi_table_lsapic *)header;
 
60
        if (!lsapic)
 
61
                return -EINVAL;
 
62
 
 
63
        if (lsapic_nbr < dom0->max_vcpus && dom0->vcpu[lsapic_nbr] != NULL)
 
64
                enable = 1;
 
65
        else
 
66
                enable = 0;
 
67
 
 
68
        if (lsapic->flags.enabled && enable) {
 
69
                printk("enable lsapic entry: 0x%lx\n", (u64) lsapic);
 
70
                lsapic->id = lsapic_nbr;
 
71
                lsapic->eid = 0;
 
72
                lsapic_nbr++;
 
73
        } else if (lsapic->flags.enabled) {
 
74
                printk("DISABLE lsapic entry: 0x%lx\n", (u64) lsapic);
 
75
                lsapic->flags.enabled = 0;
 
76
                lsapic->id = 0;
 
77
                lsapic->eid = 0;
 
78
        }
 
79
        return 0;
 
80
}
 
81
 
 
82
static int __init
 
83
acpi_patch_plat_int_src(struct acpi_subtable_header * header,
 
84
                        const unsigned long end)
 
85
{
 
86
        struct acpi_table_plat_int_src *plintsrc;
 
87
 
 
88
        plintsrc = (struct acpi_table_plat_int_src *)header;
 
89
        if (!plintsrc)
 
90
                return -EINVAL;
 
91
 
 
92
        if (plintsrc->type == ACPI_INTERRUPT_CPEI) {
 
93
                printk("ACPI_INTERRUPT_CPEI disabled for Domain0\n");
 
94
                plintsrc->type = -1;
 
95
        }
 
96
        return 0;
 
97
}
 
98
 
 
99
static int __init
 
100
acpi_update_madt_checksum(struct acpi_table_header *table)
 
101
{
 
102
        struct acpi_table_madt *acpi_madt;
 
103
 
 
104
        if (!table)
 
105
                return -EINVAL;
 
106
 
 
107
        acpi_madt = (struct acpi_table_madt *)table;
 
108
        acpi_madt->header.checksum = 0;
 
109
        acpi_madt->header.checksum = -acpi_tb_checksum((u8*)acpi_madt,
 
110
                                                       table->length);
 
111
 
 
112
        return 0;
 
113
}
 
114
 
 
115
static int __init
 
116
acpi_backup_table(struct acpi_table_header *table)
 
117
{
 
118
        struct acpi_backup_table_entry *entry;
 
119
 
 
120
        entry = xmalloc_bytes(sizeof(*entry) + table->length);
 
121
        if (!entry) {
 
122
                dprintk(XENLOG_WARNING, "Failed to allocate memory for "
 
123
                        "%.4s table backup\n", table->signature);
 
124
                return -ENOMEM;
 
125
        }
 
126
 
 
127
        entry->pa = __pa(table);
 
128
        entry->size = table->length;
 
129
 
 
130
        memcpy(entry->data, table, table->length);
 
131
 
 
132
        list_add(&entry->list, &acpi_backup_table_list);
 
133
 
 
134
        printk(XENLOG_INFO "Backup %.4s table stored @0x%p\n",
 
135
               table->signature, entry->data);
 
136
 
 
137
        return 0;
 
138
}
 
139
 
 
140
void
 
141
acpi_restore_tables()
 
142
{
 
143
        struct acpi_backup_table_entry *entry;
 
144
 
 
145
        list_for_each_entry(entry, &acpi_backup_table_list, list) {
 
146
                printk(XENLOG_INFO "Restoring backup %.4s table @0x%p\n",
 
147
                       ((struct acpi_table_header *)entry->data)->signature,
 
148
                       entry->data);
 
149
 
 
150
                memcpy(__va(entry->pa), entry->data, entry->size);
 
151
                /* Only called from kexec path, no need to free entries */
 
152
        }
 
153
}
 
154
 
 
155
static int __init __acpi_table_disable(struct acpi_table_header *header)
 
156
{
 
157
        printk("Disabling ACPI table: %4.4s\n", header->signature);
 
158
 
 
159
        memcpy(header->oem_id, "xxxxxx", 6);
 
160
        memcpy(header->oem_id+1, header->signature, 4);
 
161
        memcpy(header->oem_table_id, "Xen     ", 8);
 
162
        memcpy(header->signature, "OEMx", 4);
 
163
        header->checksum = 0;
 
164
        header->checksum = -acpi_tb_checksum((u8*)header, header->length);
 
165
 
 
166
        return 0;
 
167
}
 
168
 
 
169
static void __init acpi_table_disable(char *id)
 
170
{
 
171
        acpi_table_parse(id, __acpi_table_disable);
 
172
}
 
173
 
 
174
/* base is physical address of acpi table */
 
175
static void __init touch_acpi_table(void)
 
176
{
 
177
        struct acpi_table_header *madt = NULL;
 
178
 
 
179
        lsapic_nbr = 0;
 
180
 
 
181
        acpi_get_table(ACPI_SIG_MADT, 0, &madt);
 
182
 
 
183
        /*
 
184
         * Modify dom0 MADT:
 
185
         *  - Disable CPUs that would exceed max vCPUs for the domain
 
186
         *  - Virtualize id/eid for indexing into domain vCPU array
 
187
         *  - Hide CPEI interrupt source
 
188
         *
 
189
         * ACPI tables must be backed-up before modification!
 
190
         *
 
191
         * We update the checksum each time we modify to keep the
 
192
         * ACPI CA from warning about invalid checksums.
 
193
         */
 
194
        acpi_table_parse(ACPI_SIG_MADT, acpi_backup_table);
 
195
 
 
196
        if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_update_lsapic, 0) < 0)
 
197
                printk("Error parsing MADT - no LAPIC entries\n");
 
198
 
 
199
        acpi_update_madt_checksum(madt);
 
200
 
 
201
        if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC,
 
202
                                  acpi_patch_plat_int_src, 0) < 0)
 
203
                printk("Error parsing MADT - no PLAT_INT_SRC entries\n");
 
204
 
 
205
        acpi_update_madt_checksum(madt);
 
206
 
 
207
        /*
 
208
         * SRAT & SLIT tables aren't useful for Dom0 until
 
209
         * we support more NUMA configuration information in Xen.
 
210
         *
 
211
         * NB - backup ACPI tables first.
 
212
         */
 
213
        acpi_table_parse(ACPI_SIG_SRAT, acpi_backup_table);
 
214
        acpi_table_parse(ACPI_SIG_SLIT, acpi_backup_table);
 
215
 
 
216
        acpi_table_disable(ACPI_SIG_SRAT);
 
217
        acpi_table_disable(ACPI_SIG_SLIT);
 
218
        return;
 
219
}
 
220
 
 
221
void __init efi_systable_init_dom0(struct fw_tables *tables)
 
222
{
 
223
        int i = 1;
 
224
 
 
225
        touch_acpi_table();
 
226
 
 
227
        /* Write messages to the console.  */
 
228
        printk("Domain0 EFI passthrough:");
 
229
        if (efi.mps != EFI_INVALID_TABLE_ADDR) {
 
230
                tables->efi_tables[i].guid = MPS_TABLE_GUID;
 
231
                tables->efi_tables[i].table = efi.mps;
 
232
                printk(" MPS=0x%lx", tables->efi_tables[i].table);
 
233
                i++;
 
234
        }
 
235
        if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) {
 
236
                tables->efi_tables[i].guid = ACPI_20_TABLE_GUID;
 
237
                tables->efi_tables[i].table = efi.acpi20;
 
238
                printk(" ACPI 2.0=0x%lx", tables->efi_tables[i].table);
 
239
                i++;
 
240
        }
 
241
        if (efi.acpi != EFI_INVALID_TABLE_ADDR) {
 
242
                tables->efi_tables[i].guid = ACPI_TABLE_GUID;
 
243
                tables->efi_tables[i].table = efi.acpi;
 
244
                printk(" ACPI=0x%lx", tables->efi_tables[i].table);
 
245
                i++;
 
246
        }
 
247
        if (efi.smbios != EFI_INVALID_TABLE_ADDR) {
 
248
                tables->efi_tables[i].guid = SMBIOS_TABLE_GUID;
 
249
                tables->efi_tables[i].table = efi.smbios;
 
250
                printk(" SMBIOS=0x%lx", tables->efi_tables[i].table);
 
251
                i++;
 
252
        }
 
253
        if (efi.hcdp != EFI_INVALID_TABLE_ADDR) {
 
254
                tables->efi_tables[i].guid = HCDP_TABLE_GUID;
 
255
                tables->efi_tables[i].table = efi.hcdp;
 
256
                printk(" HCDP=0x%lx", tables->efi_tables[i].table);
 
257
                i++;
 
258
        }
 
259
        printk("\n");
 
260
        BUG_ON(i > NUM_EFI_SYS_TABLES);
 
261
}
 
262
 
 
263
static void __init
 
264
setup_dom0_memmap_info(struct domain *d, struct fw_tables *tables)
 
265
{
 
266
        int i;
 
267
        size_t size;
 
268
        unsigned int num_pages;
 
269
        efi_memory_desc_t *md;
 
270
        efi_memory_desc_t *last_mem_md = NULL;
 
271
        xen_ia64_memmap_info_t *memmap_info;
 
272
        unsigned long paddr_start;
 
273
        unsigned long paddr_end;
 
274
 
 
275
        size = sizeof(*memmap_info) +
 
276
                (tables->num_mds + 1) * sizeof(tables->efi_memmap[0]);
 
277
        num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
278
        for (i = tables->num_mds - 1; i >= 0; i--) {
 
279
                md = &tables->efi_memmap[i];
 
280
                if (md->attribute == EFI_MEMORY_WB &&
 
281
                    md->type == EFI_CONVENTIONAL_MEMORY &&
 
282
                    md->num_pages >
 
283
                    ((num_pages + 1) << (PAGE_SHIFT - EFI_PAGE_SHIFT))) {
 
284
                        last_mem_md = md;
 
285
                        break;
 
286
                }
 
287
        }
 
288
 
 
289
        if (last_mem_md == NULL) {
 
290
                printk("%s: warning: "
 
291
                       "no dom0 contiguous memory to hold memory map\n",
 
292
                       __func__);
 
293
                return;
 
294
        }
 
295
        paddr_end = last_mem_md->phys_addr +
 
296
            (last_mem_md->num_pages << EFI_PAGE_SHIFT);
 
297
        paddr_start = (paddr_end - (num_pages << PAGE_SHIFT)) & PAGE_MASK;
 
298
        last_mem_md->num_pages -= (paddr_end - paddr_start) >> EFI_PAGE_SHIFT;
 
299
 
 
300
        md = &tables->efi_memmap[tables->num_mds];
 
301
        tables->num_mds++;
 
302
        md->type = EFI_RUNTIME_SERVICES_DATA;
 
303
        md->phys_addr = paddr_start;
 
304
        md->virt_addr = 0;
 
305
        md->num_pages = num_pages << (PAGE_SHIFT - EFI_PAGE_SHIFT);
 
306
        md->attribute = EFI_MEMORY_WB;
 
307
 
 
308
        BUG_ON(tables->fw_tables_size <
 
309
               sizeof(*tables) +
 
310
               sizeof(tables->efi_memmap[0]) * tables->num_mds);
 
311
        /* with this sort, md doesn't point memmap table */
 
312
        sort(tables->efi_memmap, tables->num_mds,
 
313
             sizeof(efi_memory_desc_t), efi_mdt_cmp, NULL);
 
314
 
 
315
        memmap_info = domain_mpa_to_imva(d, paddr_start);
 
316
        memmap_info->efi_memdesc_size = sizeof(md[0]);
 
317
        memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
 
318
        memmap_info->efi_memmap_size = tables->num_mds * sizeof(md[0]);
 
319
        dom_fw_copy_to(d,
 
320
                       paddr_start + offsetof(xen_ia64_memmap_info_t, memdesc),
 
321
                       &tables->efi_memmap[0], memmap_info->efi_memmap_size);
 
322
        d->shared_info->arch.memmap_info_num_pages = num_pages;
 
323
        d->shared_info->arch.memmap_info_pfn = paddr_start >> PAGE_SHIFT;
 
324
}
 
325
 
 
326
/* setup_guest() @ libxc/xc_linux_build() arranges memory for domU.
 
327
 * however no one arranges memory for dom0,
 
328
 * instead we allocate pages manually.
 
329
 */
 
330
static void
 
331
assign_new_domain0_range(struct domain *d, const efi_memory_desc_t * md)
 
332
{
 
333
        if (md->type == EFI_PAL_CODE ||
 
334
            md->type == EFI_RUNTIME_SERVICES_DATA ||
 
335
            md->type == EFI_CONVENTIONAL_MEMORY) {
 
336
                unsigned long start = md->phys_addr & PAGE_MASK;
 
337
                unsigned long end =
 
338
                        md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
 
339
                unsigned long addr;
 
340
 
 
341
                if (end == start) {
 
342
                        /* md->num_pages = 0 is allowed. */
 
343
                        return;
 
344
                }
 
345
 
 
346
                for (addr = start; addr < end; addr += PAGE_SIZE)
 
347
                        assign_new_domain0_page(d, addr);
 
348
        }
 
349
}
 
350
 
 
351
/* Complete the dom0 memmap.  */
 
352
int __init
 
353
complete_dom0_memmap(struct domain *d, struct fw_tables *tables)
 
354
{
 
355
        u64 addr;
 
356
        void *efi_map_start, *efi_map_end, *p;
 
357
        u64 efi_desc_size;
 
358
        int i;
 
359
 
 
360
        for (i = 0; i < tables->num_mds; i++)
 
361
                assign_new_domain0_range(d, &tables->efi_memmap[i]);
 
362
 
 
363
        /* Walk through all MDT entries.
 
364
           Copy all interesting entries.  */
 
365
        efi_map_start = __va(ia64_boot_param->efi_memmap);
 
366
        efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
 
367
        efi_desc_size = ia64_boot_param->efi_memdesc_size;
 
368
 
 
369
 
 
370
        /* EFI memory descriptor is using 4k page, while xen is using 16k page.
 
371
         * To avoid identity mapping for EFI_ACPI_RECLAIM_MEMORY etc. being
 
372
         * blocked by WB mapping, scan memory descriptor twice.
 
373
         * First: setup identity mapping for EFI_ACPI_RECLAIM_MEMORY etc.
 
374
         * Second: setup mapping for EFI_CONVENTIONAL_MEMORY etc.
 
375
         */
 
376
  
 
377
        /* first scan, setup identity mapping for EFI_ACPI_RECLAIM_MEMORY etc. */
 
378
        for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
 
379
                const efi_memory_desc_t *md = p;
 
380
                efi_memory_desc_t *dom_md = &tables->efi_memmap[tables->num_mds];
 
381
                u64 start = md->phys_addr;
 
382
                u64 size = md->num_pages << EFI_PAGE_SHIFT;
 
383
                u64 end = start + size;
 
384
                u64 mpaddr;
 
385
                unsigned long flags;
 
386
 
 
387
                switch (md->type) {
 
388
                case EFI_RUNTIME_SERVICES_CODE:
 
389
                case EFI_RUNTIME_SERVICES_DATA:
 
390
                case EFI_ACPI_RECLAIM_MEMORY:
 
391
                case EFI_ACPI_MEMORY_NVS:
 
392
                case EFI_RESERVED_TYPE:
 
393
                        /*
 
394
                         * Map into dom0 - We must respect protection
 
395
                         * and cache attributes.  Not all of these pages
 
396
                         * are writable!!!
 
397
                         */
 
398
                        flags = ASSIGN_writable;        /* dummy - zero */
 
399
                        if (md->attribute & EFI_MEMORY_WP)
 
400
                                flags |= ASSIGN_readonly;
 
401
                        if ((md->attribute & EFI_MEMORY_UC) &&
 
402
                            !(md->attribute & EFI_MEMORY_WB))
 
403
                                flags |= ASSIGN_nocache;
 
404
 
 
405
                        assign_domain_mach_page(d, start, size, flags);
 
406
 
 
407
                        /* Fall-through.  */
 
408
                case EFI_MEMORY_MAPPED_IO:
 
409
                        /* Will be mapped with ioremap.  */
 
410
                        /* Copy descriptor.  */
 
411
                        *dom_md = *md;
 
412
                        dom_md->virt_addr = 0;
 
413
                        tables->num_mds++;
 
414
                        break;
 
415
 
 
416
                case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
 
417
                        flags = ASSIGN_writable;        /* dummy - zero */
 
418
                        if (md->attribute & EFI_MEMORY_UC)
 
419
                                flags |= ASSIGN_nocache;
 
420
 
 
421
                        if (start > 0x1ffffffff0000000UL) {
 
422
                                mpaddr = 0x4000000000000UL - size;
 
423
                                printk(XENLOG_INFO "Remapping IO ports from "
 
424
                                       "%lx to %lx\n", start, mpaddr);
 
425
                        } else
 
426
                                mpaddr = start;
 
427
 
 
428
                        /* Map into dom0.  */
 
429
                        assign_domain_mmio_page(d, mpaddr, start, size, flags);
 
430
                        /* Copy descriptor.  */
 
431
                        *dom_md = *md;
 
432
                        dom_md->phys_addr = mpaddr;
 
433
                        dom_md->virt_addr = 0;
 
434
                        tables->num_mds++;
 
435
                        break;
 
436
 
 
437
                case EFI_CONVENTIONAL_MEMORY:
 
438
                case EFI_LOADER_CODE:
 
439
                case EFI_LOADER_DATA:
 
440
                case EFI_BOOT_SERVICES_CODE:
 
441
                case EFI_BOOT_SERVICES_DATA:
 
442
                        break;
 
443
 
 
444
                case EFI_UNUSABLE_MEMORY:
 
445
                case EFI_PAL_CODE:
 
446
                        /*
 
447
                         * We don't really need these, but holes in the
 
448
                         * memory map may cause Linux to assume there are
 
449
                         * uncacheable ranges within a granule.
 
450
                         */
 
451
                        dom_md->type = EFI_UNUSABLE_MEMORY;
 
452
                        dom_md->phys_addr = start;
 
453
                        dom_md->virt_addr = 0;
 
454
                        dom_md->num_pages = (end - start) >> EFI_PAGE_SHIFT;
 
455
                        dom_md->attribute = EFI_MEMORY_WB;
 
456
                        tables->num_mds++;
 
457
                        break;
 
458
 
 
459
                default:
 
460
                        /* Print a warning but continue.  */
 
461
                        printk("complete_dom0_memmap: warning: "
 
462
                               "unhandled MDT entry type %u\n", md->type);
 
463
                }
 
464
        }
 
465
 
 
466
 
 
467
        /* secend scan, setup mapping for EFI_CONVENTIONAL_MEMORY etc. */
 
468
        for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
 
469
                const efi_memory_desc_t *md = p;
 
470
                efi_memory_desc_t *dom_md = &tables->efi_memmap[tables->num_mds];
 
471
                u64 start = md->phys_addr;
 
472
                u64 size = md->num_pages << EFI_PAGE_SHIFT;
 
473
                u64 end = start + size;
 
474
 
 
475
                switch (md->type) {
 
476
 
 
477
                case EFI_CONVENTIONAL_MEMORY:
 
478
                case EFI_LOADER_CODE:
 
479
                case EFI_LOADER_DATA:
 
480
                case EFI_BOOT_SERVICES_CODE:
 
481
                case EFI_BOOT_SERVICES_DATA: {
 
482
                        u64 dom_md_start;
 
483
                        u64 dom_md_end;
 
484
                        unsigned long left_mem =
 
485
                                (unsigned long)(d->max_pages - d->tot_pages) <<
 
486
                                PAGE_SHIFT;
 
487
 
 
488
                        if (!(md->attribute & EFI_MEMORY_WB))
 
489
                                break;
 
490
 
 
491
                        dom_md_start = max(tables->fw_end_paddr, start);
 
492
                        dom_md_end = dom_md_start;
 
493
                        do {
 
494
                                dom_md_end = min(dom_md_end + left_mem, end);
 
495
                                if (dom_md_end < dom_md_start + PAGE_SIZE)
 
496
                                        break;
 
497
 
 
498
                                dom_md->type = EFI_CONVENTIONAL_MEMORY;
 
499
                                dom_md->phys_addr = dom_md_start;
 
500
                                dom_md->virt_addr = 0;
 
501
                                dom_md->num_pages =
 
502
                                        (dom_md_end - dom_md_start) >>
 
503
                                        EFI_PAGE_SHIFT;
 
504
                                dom_md->attribute = EFI_MEMORY_WB;
 
505
 
 
506
                                assign_new_domain0_range(d, dom_md);
 
507
                                /*
 
508
                                 * recalculate left_mem.
 
509
                                 * we might already allocated memory in
 
510
                                 * this region because of kernel loader.
 
511
                                 * So we might consumed less than
 
512
                                 * (dom_md_end - dom_md_start) above.
 
513
                                 */
 
514
                                left_mem = (unsigned long)
 
515
                                        (d->max_pages - d->tot_pages) <<
 
516
                                        PAGE_SHIFT;
 
517
                        } while (left_mem > 0 && dom_md_end < end);
 
518
 
 
519
                        if (!(dom_md_end < dom_md_start + PAGE_SIZE))
 
520
                                tables->num_mds++;
 
521
                        break;
 
522
                }
 
523
 
 
524
 
 
525
                default:
 
526
                        break;
 
527
                }
 
528
        }
 
529
 
 
530
        BUG_ON(tables->fw_tables_size <
 
531
               sizeof(*tables) +
 
532
               sizeof(tables->efi_memmap[0]) * tables->num_mds);
 
533
 
 
534
        sort(tables->efi_memmap, tables->num_mds, sizeof(efi_memory_desc_t),
 
535
             efi_mdt_cmp, NULL);
 
536
 
 
537
        // Map low-memory holes & unmapped MMIO for legacy drivers
 
538
        for (addr = 0; addr < ONE_MB; addr += PAGE_SIZE) {
 
539
                if (domain_page_mapped(d, addr))
 
540
                        continue;
 
541
 
 
542
                if (efi_mmio(addr, PAGE_SIZE)) {
 
543
                        unsigned long flags;
 
544
                        flags = ASSIGN_writable | ASSIGN_nocache;
 
545
                        assign_domain_mmio_page(d, addr, addr, PAGE_SIZE,
 
546
                                                flags);
 
547
                }
 
548
        }
 
549
        setup_dom0_memmap_info(d, tables);
 
550
        return tables->num_mds;
 
551
}
 
552
 
 
553
/*
 
554
 * Local variables:
 
555
 * mode: C
 
556
 * c-set-style: "linux"
 
557
 * c-basic-offset: 8
 
558
 * tab-width: 8
 
559
 * indent-tabs-mode: t
 
560
 * End:
 
561
 */