1 /*
2 * acpi_mmconfig.c - Architecture-Specific Low-Level ACPI Boot Support
3 *
4 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
5 * Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; If not, see <http://www.gnu.org/licenses/>.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 *
24 * copied from Linux
25 */
26
27 #include <xen/errno.h>
28 #include <xen/init.h>
29 #include <xen/acpi.h>
30 #include <xen/irq.h>
31 #include <xen/dmi.h>
32 #include <asm/fixmap.h>
33 #include <asm/page.h>
34 #include <asm/apic.h>
35 #include <asm/io_apic.h>
36 #include <asm/apic.h>
37 #include <asm/io.h>
38 #include <asm/mpspec.h>
39 #include <asm/processor.h>
40 #include <mach_apic.h>
41 #include <mach_mpparse.h>
42
43 #include "mmconfig.h"
44
45 /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
46 struct acpi_mcfg_allocation *pci_mmcfg_config;
47 int pci_mmcfg_config_num;
48
acpi_mcfg_check_entry(struct acpi_table_mcfg * mcfg,struct acpi_mcfg_allocation * cfg)49 static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
50 struct acpi_mcfg_allocation *cfg)
51 {
52 int year;
53
54 if (cfg->address < 0xFFFFFFFF)
55 return 0;
56
57 if (!strncmp(mcfg->header.oem_id, "SGI", 3))
58 return 0;
59
60 if (mcfg->header.revision >= 1 &&
61 dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) &&
62 year >= 2010)
63 return 0;
64
65 printk(KERN_ERR "MCFG region for %04x:%02x-%02x at %#"PRIx64
66 " (above 4GB) ignored\n",
67 cfg->pci_segment, cfg->start_bus_number, cfg->end_bus_number,
68 cfg->address);
69 return -EINVAL;
70 }
71
acpi_parse_mcfg(struct acpi_table_header * header)72 int __init acpi_parse_mcfg(struct acpi_table_header *header)
73 {
74 struct acpi_table_mcfg *mcfg;
75 unsigned long i;
76
77 if (!header)
78 return -EINVAL;
79
80 mcfg = (struct acpi_table_mcfg *)header;
81
82 /* how many config structures do we have */
83 pci_mmcfg_config_num = 0;
84 i = header->length - sizeof(struct acpi_table_mcfg);
85 while (i >= sizeof(struct acpi_mcfg_allocation)) {
86 ++pci_mmcfg_config_num;
87 i -= sizeof(struct acpi_mcfg_allocation);
88 };
89 if (pci_mmcfg_config_num == 0) {
90 printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
91 return -ENODEV;
92 }
93
94 pci_mmcfg_config = xmalloc_array(struct acpi_mcfg_allocation,
95 pci_mmcfg_config_num);
96 if (!pci_mmcfg_config) {
97 printk(KERN_WARNING PREFIX
98 "No memory for MCFG config tables\n");
99 pci_mmcfg_config_num = 0;
100 return -ENOMEM;
101 }
102
103 memcpy(pci_mmcfg_config, &mcfg[1],
104 pci_mmcfg_config_num * sizeof(*pci_mmcfg_config));
105
106 for (i = 0; i < pci_mmcfg_config_num; ++i) {
107 if (acpi_mcfg_check_entry(mcfg, &pci_mmcfg_config[i])) {
108 xfree(pci_mmcfg_config);
109 pci_mmcfg_config_num = 0;
110 return -ENODEV;
111 }
112 pci_add_segment(pci_mmcfg_config[i].pci_segment);
113 }
114
115 return 0;
116 }
117