# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 07a892f1260933c584f781f2262dfa59a5ba8d70
# Parent b9b411b505878f7600871c68de989d33c1994cf7
More upgrades of Xen code to linux-2.6.16-rc2.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r b9b411b50587 -r 07a892f12609 xen/arch/x86/acpi/boot.c
--- a/xen/arch/x86/acpi/boot.c Tue Feb 14 15:23:43 2006
+++ b/xen/arch/x86/acpi/boot.c Tue Feb 14 17:25:10 2006
@@ -28,6 +28,7 @@
#include <xen/init.h>
#include <xen/acpi.h>
#include <xen/irq.h>
+#include <xen/dmi.h>
#include <asm/fixmap.h>
#include <asm/page.h>
#include <asm/apic.h>
@@ -75,7 +76,7 @@
#define MAX_MADT_ENTRIES 256
u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] =
- { [0 ... MAX_MADT_ENTRIES-1] = 0xff };
+ {[0 ... MAX_MADT_ENTRIES - 1] = 0xff };
EXPORT_SYMBOL(x86_acpiid_to_apicid);
/* --------------------------------------------------------------------------
@@ -105,7 +106,7 @@
unsigned long base, offset, mapped_size;
int idx;
- if (phys + size < 8*1024*1024)
+ if (phys + size < 8 * 1024 * 1024)
return __va(phys);
offset = phys & (PAGE_SIZE - 1);
@@ -128,45 +129,15 @@
return ((char *) base + offset);
}
-#ifdef CONFIG_PCI_MMCONFIG
-static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
-{
- struct acpi_table_mcfg *mcfg;
+#ifdef CONFIG_X86_LOCAL_APIC
+static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size)
+{
+ struct acpi_table_madt *madt = NULL;
if (!phys_addr || !size)
return -EINVAL;
- mcfg = (struct acpi_table_mcfg *) __acpi_map_table(phys_addr, size);
- if (!mcfg) {
- printk(KERN_WARNING PREFIX "Unable to map MCFG\n");
- return -ENODEV;
- }
-
- if (mcfg->base_reserved) {
- printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n");
- return -ENODEV;
- }
-
- pci_mmcfg_base_addr = mcfg->base_address;
-
- return 0;
-}
-#else
-#define acpi_parse_mcfg NULL
-#endif /* !CONFIG_PCI_MMCONFIG */
-
-#ifdef CONFIG_X86_LOCAL_APIC
-static int __init
-acpi_parse_madt (
- unsigned long phys_addr,
- unsigned long size)
-{
- struct acpi_table_madt *madt = NULL;
-
- if (!phys_addr || !size)
- return -EINVAL;
-
- madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size);
+ madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size);
if (!madt) {
printk(KERN_WARNING PREFIX "Unable to map MADT\n");
return -ENODEV;
@@ -184,40 +155,35 @@
return 0;
}
-
static int __init
-acpi_parse_lapic (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_lapic(acpi_table_entry_header * header, const unsigned long end)
{
struct acpi_table_lapic *processor = NULL;
- processor = (struct acpi_table_lapic*) header;
+ processor = (struct acpi_table_lapic *)header;
if (BAD_MADT_ENTRY(processor, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
- /* no utility in registering a disabled processor */
- if (processor->flags.enabled == 0)
- return 0;
+ /* Register even disabled CPUs for cpu hotplug */
x86_acpiid_to_apicid[processor->acpi_id] = processor->id;
- mp_register_lapic (
- processor->id, /* APIC ID */
- processor->flags.enabled); /* Enabled? */
+ mp_register_lapic(processor->id, /* APIC ID */
+ processor->flags.enabled); /* Enabled? */
return 0;
}
static int __init
-acpi_parse_lapic_addr_ovr (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_lapic_addr_ovr(acpi_table_entry_header * header,
+ const unsigned long end)
{
struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;
- lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
+ lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr *)header;
if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
return -EINVAL;
@@ -228,12 +194,11 @@
}
static int __init
-acpi_parse_lapic_nmi (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_lapic_nmi(acpi_table_entry_header * header, const unsigned long end)
{
struct acpi_table_lapic_nmi *lapic_nmi = NULL;
- lapic_nmi = (struct acpi_table_lapic_nmi*) header;
+ lapic_nmi = (struct acpi_table_lapic_nmi *)header;
if (BAD_MADT_ENTRY(lapic_nmi, end))
return -EINVAL;
@@ -246,39 +211,35 @@
return 0;
}
-
-#endif /*CONFIG_X86_LOCAL_APIC*/
+#endif /*CONFIG_X86_LOCAL_APIC */
#if defined(CONFIG_X86_IO_APIC) /*&& defined(CONFIG_ACPI_INTERPRETER)*/
static int __init
-acpi_parse_ioapic (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_ioapic(acpi_table_entry_header * header, const unsigned long end)
{
struct acpi_table_ioapic *ioapic = NULL;
- ioapic = (struct acpi_table_ioapic*) header;
+ ioapic = (struct acpi_table_ioapic *)header;
if (BAD_MADT_ENTRY(ioapic, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
- mp_register_ioapic (
- ioapic->id,
- ioapic->address,
- ioapic->global_irq_base);
-
+ mp_register_ioapic(ioapic->id,
+ ioapic->address, ioapic->global_irq_base);
+
return 0;
}
static int __init
-acpi_parse_int_src_ovr (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_int_src_ovr(acpi_table_entry_header * header,
+ const unsigned long end)
{
struct acpi_table_int_src_ovr *intsrc = NULL;
- intsrc = (struct acpi_table_int_src_ovr*) header;
+ intsrc = (struct acpi_table_int_src_ovr *)header;
if (BAD_MADT_ENTRY(intsrc, end))
return -EINVAL;
@@ -291,23 +252,19 @@
return 0;
}
- mp_override_legacy_irq (
- intsrc->bus_irq,
- intsrc->flags.polarity,
- intsrc->flags.trigger,
- intsrc->global_irq);
-
- return 0;
-}
-
+ mp_override_legacy_irq(intsrc->bus_irq,
+ intsrc->flags.polarity,
+ intsrc->flags.trigger, intsrc->global_irq);
+
+ return 0;
+}
static int __init
-acpi_parse_nmi_src (
- acpi_table_entry_header *header, const unsigned long end)
+acpi_parse_nmi_src(acpi_table_entry_header * header, const unsigned long end)
{
struct acpi_table_nmi_src *nmi_src = NULL;
- nmi_src = (struct acpi_table_nmi_src*) header;
+ nmi_src = (struct acpi_table_nmi_src *)header;
if (BAD_MADT_ENTRY(nmi_src, end))
return -EINVAL;
@@ -322,9 +279,7 @@
#endif /* CONFIG_X86_IO_APIC */
static unsigned long __init
-acpi_scan_rsdp (
- unsigned long start,
- unsigned long length)
+acpi_scan_rsdp(unsigned long start, unsigned long length)
{
unsigned long offset = 0;
unsigned long sig_len = sizeof("RSD PTR ") - 1;
@@ -334,7 +289,7 @@
* RSDP signature.
*/
for (offset = 0; offset < length; offset += 16) {
- if (strncmp((char *) (start + offset), "RSD PTR ", sig_len))
+ if (strncmp((char *)(start + offset), "RSD PTR ", sig_len))
continue;
return (start + offset);
}
@@ -349,7 +304,7 @@
if (!phys_addr || !size)
return -EINVAL;
- sb = (struct acpi_table_sbf *) __acpi_map_table(phys_addr, size);
+ sb = (struct acpi_table_sbf *)__acpi_map_table(phys_addr, size);
if (!sb) {
printk(KERN_WARNING PREFIX "Unable to map SBF\n");
return -ENODEV;
@@ -370,7 +325,7 @@
if (!phys || !size)
return -EINVAL;
- hpet_tbl = (struct acpi_table_hpet *) __acpi_map_table(phys, size);
+ hpet_tbl = (struct acpi_table_hpet *)__acpi_map_table(phys, size);
if (!hpet_tbl) {
printk(KERN_WARNING PREFIX "Unable to map HPET\n");
return -ENODEV;
@@ -412,8 +367,8 @@
{
struct fadt_descriptor_rev2 *fadt = NULL;
- fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size);
- if(!fadt) {
+ fadt = (struct fadt_descriptor_rev2 *)__acpi_map_table(phys, size);
+ if (!fadt) {
printk(KERN_WARNING PREFIX "Unable to map FADT\n");
return 0;
}
@@ -421,29 +376,42 @@
#ifdef CONFIG_ACPI_INTERPRETER
/* initialize sci_int early for INT_SRC_OVR MADT parsing */
acpi_fadt.sci_int = fadt->sci_int;
+
+ /* initialize rev and apic_phys_dest_mode for x86_64 genapic */
+ acpi_fadt.revision = fadt->revision;
+ acpi_fadt.force_apic_physical_destination_mode =
+ fadt->force_apic_physical_destination_mode;
#endif
#ifdef CONFIG_X86_PM_TIMER
/* detect the location of the ACPI PM Timer */
if (fadt->revision >= FADT2_REVISION_ID) {
/* FADT rev. 2 */
- if (fadt->xpm_tmr_blk.address_space_id !=
ACPI_ADR_SPACE_SYSTEM_IO)
+ if (fadt->xpm_tmr_blk.address_space_id !=
+ ACPI_ADR_SPACE_SYSTEM_IO)
return 0;
pmtmr_ioport = fadt->xpm_tmr_blk.address;
+ /*
+ * "X" fields are optional extensions to the original V1.0
+ * fields, so we must selectively expand V1.0 fields if the
+ * corresponding X field is zero.
+ */
+ if (!pmtmr_ioport)
+ pmtmr_ioport = fadt->V1_pm_tmr_blk;
} else {
/* FADT rev. 1 */
pmtmr_ioport = fadt->V1_pm_tmr_blk;
}
if (pmtmr_ioport)
- printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n",
pmtmr_ioport);
-#endif
- return 0;
-}
-
-
-unsigned long __init
-acpi_find_rsdp (void)
+ printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n",
+ pmtmr_ioport);
+#endif
+ return 0;
+}
+
+
+unsigned long __init acpi_find_rsdp(void)
{
unsigned long rsdp_phys = 0;
@@ -459,9 +427,9 @@
* Scan memory looking for the RSDP signature. First search EBDA (low
* memory) paragraphs and then search upper memory (E0000-FFFFF).
*/
- rsdp_phys = acpi_scan_rsdp (0, 0x400);
+ rsdp_phys = acpi_scan_rsdp(0, 0x400);
if (!rsdp_phys)
- rsdp_phys = acpi_scan_rsdp (0xE0000, 0x20000);
+ rsdp_phys = acpi_scan_rsdp(0xE0000, 0x20000);
return rsdp_phys;
}
@@ -471,8 +439,7 @@
* Parse LAPIC entries in MADT
* returns 0 on success, < 0 on error
*/
-static int __init
-acpi_parse_madt_lapic_entries(void)
+static int __init acpi_parse_madt_lapic_entries(void)
{
int count;
@@ -481,9 +448,12 @@
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/
- count = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR,
acpi_parse_lapic_addr_ovr, 0);
+ count =
+ acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR,
+ acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
- printk(KERN_ERR PREFIX "Error parsing LAPIC address override
entry\n");
+ printk(KERN_ERR PREFIX
+ "Error parsing LAPIC address override entry\n");
return count;
}
@@ -495,14 +465,14 @@
printk(KERN_ERR PREFIX "No LAPIC entries present\n");
/* TBD: Cleanup to allow fallback to MPS */
return -ENODEV;
- }
- else if (count < 0) {
+ } else if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
}
- count = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI,
acpi_parse_lapic_nmi, 0);
+ count =
+ acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0);
if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* TBD: Cleanup to allow fallback to MPS */
@@ -517,8 +487,7 @@
* Parse IOAPIC related entries in MADT
* returns 0 on success, < 0 on error
*/
-static int __init
-acpi_parse_madt_ioapic_entries(void)
+static int __init acpi_parse_madt_ioapic_entries(void)
{
int count;
@@ -541,19 +510,23 @@
return -ENODEV;
}
- count = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic,
MAX_IO_APICS);
+ count =
+ acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic,
+ MAX_IO_APICS);
if (!count) {
printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
return -ENODEV;
- }
- else if (count < 0) {
+ } else if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
return count;
}
- count = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR,
acpi_parse_int_src_ovr, NR_IRQ_VECTORS);
+ count =
+ acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr,
+ NR_IRQ_VECTORS);
if (count < 0) {
- printk(KERN_ERR PREFIX "Error parsing interrupt source
overrides entry\n");
+ printk(KERN_ERR PREFIX
+ "Error parsing interrupt source overrides entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
}
@@ -570,7 +543,9 @@
/* Fill in identity legacy mapings where no override */
mp_config_acpi_legacy_irqs();
- count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src,
NR_IRQ_VECTORS);
+ count =
+ acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src,
+ NR_IRQ_VECTORS);
if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
@@ -587,8 +562,7 @@
#endif /* !(CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER) */
-static void __init
-acpi_process_madt(void)
+static void __init acpi_process_madt(void)
{
#ifdef CONFIG_X86_LOCAL_APIC
int count, error;
@@ -621,13 +595,226 @@
/*
* Dell Precision Workstation 410, 610 come here.
*/
- printk(KERN_ERR PREFIX "Invalid BIOS MADT, disabling
ACPI\n");
+ printk(KERN_ERR PREFIX
+ "Invalid BIOS MADT, disabling ACPI\n");
disable_acpi();
}
}
#endif
return;
}
+
+extern int acpi_force;
+
+#ifdef __i386__
+
+static int __init disable_acpi_irq(struct dmi_system_id *d)
+{
+ if (!acpi_force) {
+ printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n",
+ d->ident);
+ acpi_noirq_set();
+ }
+ return 0;
+}
+
+static int __init disable_acpi_pci(struct dmi_system_id *d)
+{
+ if (!acpi_force) {
+ printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n",
+ d->ident);
+ /*acpi_disable_pci();*/
+ }
+ return 0;
+}
+
+static int __init dmi_disable_acpi(struct dmi_system_id *d)
+{
+ if (!acpi_force) {
+ printk(KERN_NOTICE "%s detected: acpi off\n", d->ident);
+ disable_acpi();
+ } else {
+ printk(KERN_NOTICE
+ "Warning: DMI blacklist says broken, but acpi forced\n");
+ }
+ return 0;
+}
+
+/*
+ * Limit ACPI to CPU enumeration for HT
+ */
+static int __init force_acpi_ht(struct dmi_system_id *d)
+{
+ if (!acpi_force) {
+ printk(KERN_NOTICE "%s detected: force use of acpi=ht\n",
+ d->ident);
+ disable_acpi();
+ acpi_ht = 1;
+ } else {
+ printk(KERN_NOTICE
+ "Warning: acpi=force overrules DMI blacklist:
acpi=ht\n");
+ }
+ return 0;
+}
+
+/*
+ * If your system is blacklisted here, but you find that acpi=force
+ * works for you, please contact acpi-devel@xxxxxxxxxxxxxxx
+ */
+static struct dmi_system_id __initdata acpi_dmi_table[] = {
+ /*
+ * Boxes that need ACPI disabled
+ */
+ {
+ .callback = dmi_disable_acpi,
+ .ident = "IBM Thinkpad",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "2629H1G"),
+ },
+ },
+
+ /*
+ * Boxes that need acpi=ht
+ */
+ {
+ .callback = force_acpi_ht,
+ .ident = "FSC Primergy T850",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "DELL GX240",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "HP VISUALIZE NT Workstation",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "Compaq Workstation W8000",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "ASUS P4B266",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "P4B266"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "ASUS P2B-DS",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "P2B-DS"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "ASUS CUR-DLS",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "CUR-DLS"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "ABIT i440BX-W83977",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
+ DMI_MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "IBM Bladecenter",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "IBM eServer xSeries 360",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "IBM eserver xSeries 330",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "IBM eserver xSeries 440",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
+ },
+ },
+
+ /*
+ * Boxes that need ACPI PCI IRQ routing disabled
+ */
+ {
+ .callback = disable_acpi_irq,
+ .ident = "ASUS A7V",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
+ DMI_MATCH(DMI_BOARD_NAME, "<A7V>"),
+ /* newer BIOS, Revision 1011, does work */
+ DMI_MATCH(DMI_BIOS_VERSION,
+ "ASUS A7V ACPI BIOS Revision 1007"),
+ },
+ },
+
+ /*
+ * Boxes that need ACPI PCI IRQ routing and PCI scan disabled
+ */
+ { /* _BBN 0 bug */
+ .callback = disable_acpi_pci,
+ .ident = "ASUS PR-DLS",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "PR-DLS"),
+ DMI_MATCH(DMI_BIOS_VERSION,
+ "ASUS PR-DLS ACPI BIOS Revision 1010"),
+ DMI_MATCH(DMI_BIOS_DATE, "03/21/2003")
+ },
+ },
+ {
+ .callback = disable_acpi_pci,
+ .ident = "Acer TravelMate 36x Laptop",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+ },
+ },
+ {}
+};
+
+#endif /* __i386__ */
/*
* acpi_boot_table_init() and acpi_boot_init()
@@ -652,10 +839,13 @@
* !0: failure
*/
-int __init
-acpi_boot_table_init(void)
+int __init acpi_boot_table_init(void)
{
int error;
+
+#ifdef __i386__
+ dmi_check_system(acpi_dmi_table);
+#endif
/*
* If acpi_disabled, bail out
@@ -717,8 +907,7 @@
acpi_process_madt();
acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
- acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
-
- return 0;
-}
-
+
+ return 0;
+}
+
diff -r b9b411b50587 -r 07a892f12609 xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c Tue Feb 14 15:23:43 2006
+++ b/xen/arch/x86/apic.c Tue Feb 14 17:25:10 2006
@@ -38,9 +38,53 @@
#include <io_ports.h>
/*
+ * Knob to control our willingness to enable the local APIC.
+ */
+int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
+
+/*
* Debug level
*/
int apic_verbosity;
+
+
+static void apic_pm_activate(void);
+
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(unsigned int irq)
+{
+ printk("unexpected IRQ trap at vector %02x\n", irq);
+ /*
+ * Currently unexpected vectors happen only on SMP and APIC.
+ * We _must_ ack these because every local APIC has only N
+ * irq slots per priority level, and a 'hanging, unacked' IRQ
+ * holds up an irq slot - in excessive cases (when multiple
+ * unexpected vectors occur) that might lock up the APIC
+ * completely.
+ */
+ ack_APIC_irq();
+}
+
+void __init apic_intr_init(void)
+{
+#ifdef CONFIG_SMP
+ smp_intr_init();
+#endif
+ /* self generated IPI for local APIC timer */
+ set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
+
+ /* IPI vectors for APIC spurious and error interrupts */
+ set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
+ set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+
+ /* thermal monitor LVT interrupt */
+#ifdef CONFIG_X86_MCE_P4THERMAL
+ set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
+#endif
+}
/* Using APIC to generate smp_local_timer_interrupt? */
int using_apic_timer = 0;
@@ -148,7 +192,7 @@
enable_apic_mode();
}
-void disconnect_bsp_APIC(void)
+void disconnect_bsp_APIC(int virt_wire_setup)
{
if (pic_mode) {
/*
@@ -162,6 +206,42 @@
outb(0x70, 0x22);
outb(0x00, 0x23);
}
+ else {
+ /* Go back to Virtual Wire compatibility mode */
+ unsigned long value;
+
+ /* For the spurious interrupt use vector F, and enable it */
+ value = apic_read(APIC_SPIV);
+ value &= ~APIC_VECTOR_MASK;
+ value |= APIC_SPIV_APIC_ENABLED;
+ value |= 0xf;
+ apic_write_around(APIC_SPIV, value);
+
+ if (!virt_wire_setup) {
+ /* For LVT0 make it edge triggered, active high, external and
enabled */
+ value = apic_read(APIC_LVT0);
+ value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
+ APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+ APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
+ value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+ value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
+ apic_write_around(APIC_LVT0, value);
+ }
+ else {
+ /* Disable LVT0 */
+ apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
+ }
+
+ /* For LVT1 make it edge triggered, active high, nmi and enabled */
+ value = apic_read(APIC_LVT1);
+ value &= ~(
+ APIC_MODE_MASK | APIC_SEND_PENDING |
+ APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+ APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
+ value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+ value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
+ apic_write_around(APIC_LVT1, value);
+ }
}
void disable_local_APIC(void)
@@ -306,7 +386,7 @@
apic_write_around(APIC_LVT1, value);
}
-void __init setup_local_APIC (void)
+void __devinit setup_local_APIC(void)
{
unsigned long oldvalue, value, ver, maxlvt;
@@ -453,17 +533,15 @@
if (nmi_watchdog == NMI_LOCAL_APIC)
setup_apic_nmi_watchdog();
-}
+ apic_pm_activate();
+}
+
+static void apic_pm_activate(void) { }
/*
* Detect and enable local APICs on non-SMP boards.
* Original code written by Keir Fraser.
*/
-
-/*
- * Knob to control our willingness to enable the local APIC.
- */
-int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
static void __init lapic_disable(char *str)
{
@@ -497,9 +575,6 @@
/* Disabled by kernel option? */
if (enable_local_apic < 0)
return -1;
-
- /* Workaround for us being called before identify_cpu(). */
- /*get_cpu_vendor(&boot_cpu_data); Not for Xen */
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_AMD:
@@ -564,6 +639,8 @@
printk("Found and enabled local APIC!\n");
+ apic_pm_activate();
+
return 0;
no_apic:
@@ -824,26 +901,27 @@
void __init setup_boot_APIC_clock(void)
{
+ unsigned long flags;
apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n");
using_apic_timer = 1;
- local_irq_disable();
-
+ local_irq_save(flags);
+
calibration_result = calibrate_APIC_clock();
/*
* Now set up the timer for real.
*/
setup_APIC_timer(calibration_result);
- local_irq_enable();
-}
-
-void __init setup_secondary_APIC_clock(void)
+ local_irq_restore(flags);
+}
+
+void __devinit setup_secondary_APIC_clock(void)
{
setup_APIC_timer(calibration_result);
}
-void __init disable_APIC_timer(void)
+void disable_APIC_timer(void)
{
if (using_apic_timer) {
unsigned long v;
@@ -941,6 +1019,7 @@
{
unsigned long v;
+ irq_enter();
/*
* Check if this really is a spurious interrupt and ACK it
* if it is a vectored one. Just in case...
@@ -953,6 +1032,7 @@
/* see sw-dev-man vol 3, chapter 7.4.13.5 */
printk(KERN_INFO "spurious APIC interrupt on CPU#%d, should never
happen.\n",
smp_processor_id());
+ irq_exit();
}
/*
@@ -963,6 +1043,7 @@
{
unsigned long v, v1;
+ irq_enter();
/* First tickle the hardware, only then report what went on. -- REW */
v = apic_read(APIC_ESR);
apic_write(APIC_ESR, 0);
@@ -982,6 +1063,7 @@
*/
printk (KERN_DEBUG "APIC error on CPU%d: %02lx(%02lx)\n",
smp_processor_id(), v , v1);
+ irq_exit();
}
/*
diff -r b9b411b50587 -r 07a892f12609 xen/arch/x86/cpu/mcheck/p4.c
--- a/xen/arch/x86/cpu/mcheck/p4.c Tue Feb 14 15:23:43 2006
+++ b/xen/arch/x86/cpu/mcheck/p4.c Tue Feb 14 17:25:10 2006
@@ -71,9 +71,9 @@
fastcall void smp_thermal_interrupt(struct cpu_user_regs *regs)
{
- irq_enter(smp_processor_id());
+ irq_enter();
vendor_thermal_interrupt(regs);
- irq_exit(smp_processor_id());
+ irq_exit();
}
/* P4/Xeon Thermal regulation detect and init */
diff -r b9b411b50587 -r 07a892f12609 xen/arch/x86/i8259.c
--- a/xen/arch/x86/i8259.c Tue Feb 14 15:23:43 2006
+++ b/xen/arch/x86/i8259.c Tue Feb 14 17:25:10 2006
@@ -374,25 +374,7 @@
irq_desc[LEGACY_VECTOR(i)].handler = &i8259A_irq_type;
}
- /*
- * IRQ0 must be given a fixed assignment and initialized,
- * because it's used before the IO-APIC is set up.
- */
- irq_vector[0] = FIRST_DEVICE_VECTOR;
- vector_irq[FIRST_DEVICE_VECTOR] = 0;
-
- /* Various IPI functions. */
- set_intr_gate(EVENT_CHECK_VECTOR, event_check_interrupt);
- set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
- set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
-
- /* Self-generated IPI for local APIC timer. */
- set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
- /* IPI vectors for APIC spurious and error interrupts. */
- set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
- set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
- set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
+ apic_intr_init();
/* Set the clock to HZ Hz */
#define CLOCK_TICK_RATE 1193180 /* crystal freq (Hz) */
diff -r b9b411b50587 -r 07a892f12609 xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c Tue Feb 14 15:23:43 2006
+++ b/xen/arch/x86/io_apic.c Tue Feb 14 17:25:10 2006
@@ -35,11 +35,18 @@
#include <mach_apic.h>
#include <io_ports.h>
+#define set_irq_info(irq, mask) ((void)0)
+#define set_native_irq_info(irq, mask) ((void)0)
+
+/* Different to Linux: our implementation can be simpler. */
#define make_8259A_irq(irq) (io_apic_irqs &= ~(1<<(irq)))
int (*ioapic_renumber_irq)(int ioapic, int irq);
atomic_t irq_mis_count;
+/* Where if anywhere is the i8259 connect in external int mode */
+static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
+
static DEFINE_SPINLOCK(ioapic_lock);
int skip_ioapic_setup;
@@ -48,6 +55,8 @@
* # of IRQ routing registers
*/
int nr_ioapic_registers[MAX_IO_APICS];
+
+int disable_timer_pin_1 __initdata;
/*
* Rough estimation of how many shared IRQs there are, can
@@ -67,7 +76,7 @@
int apic, pin, next;
} irq_2_pin[PIN_MAP_SIZE];
-int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
+int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
/*
* The common case is 1:1 IRQ<->pin mappings. Sometimes there are
@@ -173,7 +182,7 @@
spin_unlock_irqrestore(&ioapic_lock, flags);
}
-void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
+static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
{
struct IO_APIC_route_entry entry;
unsigned long flags;
@@ -206,13 +215,21 @@
clear_IO_APIC_pin(apic, pin);
}
+#ifdef CONFIG_SMP
static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
{
unsigned long flags;
int pin;
struct irq_pin_list *entry = irq_2_pin + irq;
unsigned int apicid_value;
+ cpumask_t tmp;
+ cpus_and(tmp, cpumask, cpu_online_map);
+ if (cpus_empty(tmp))
+ tmp = TARGET_CPUS;
+
+ cpus_and(cpumask, tmp, CPU_MASK_ALL);
+
apicid_value = cpu_mask_to_apicid(cpumask);
/* Prepare to do the io_apic_write */
apicid_value = apicid_value << 24;
@@ -226,8 +243,10 @@
break;
entry = irq_2_pin + entry->next;
}
+ set_irq_info(irq, cpumask);
spin_unlock_irqrestore(&ioapic_lock, flags);
}
+#endif /* CONFIG_SMP */
/*
* Find the IRQ entry number of a certain pin.
@@ -249,7 +268,7 @@
/*
* Find the pin to which IRQ[irq] (ISA) is connected
*/
-static int find_isa_irq_pin(int irq, int type)
+static int __init find_isa_irq_pin(int irq, int type)
{
int i;
@@ -269,6 +288,33 @@
return -1;
}
+static int __init find_isa_irq_apic(int irq, int type)
+{
+ int i;
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ int lbus = mp_irqs[i].mpc_srcbus;
+
+ if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+ mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+ mp_bus_id_to_type[lbus] == MP_BUS_MCA ||
+ mp_bus_id_to_type[lbus] == MP_BUS_NEC98
+ ) &&
+ (mp_irqs[i].mpc_irqtype == type) &&
+ (mp_irqs[i].mpc_srcbusirq == irq))
+ break;
+ }
+ if (i < mp_irq_entries) {
+ int apic;
+ for(apic = 0; apic < nr_ioapics; apic++) {
+ if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
+ return apic;
+ }
+ }
+
+ return -1;
+}
+
/*
* Find a specific PCI IRQ entry.
* Not an __init, possibly needed by modules
@@ -276,10 +322,11 @@
static int pin_2_irq(int idx, int apic, int pin);
/*
- * This function currently is only a helper for the i386 smp boot process where
- * we need to reprogram the ioredtbls to cater for the cpus which have come
- * online so mask in all cases should simply be TARGET_CPUS
- */
+ * This function currently is only a helper for the i386 smp boot process
where
+ * we need to reprogram the ioredtbls to cater for the cpus which have come
online
+ * so mask in all cases should simply be TARGET_CPUS
+ */
+#ifdef CONFIG_SMP
void __init setup_ioapic_dest(void)
{
int pin, ioapic, irq, irq_entry;
@@ -298,6 +345,7 @@
}
}
+#endif
/*
* EISA Edge/Level control register, ELCR
@@ -571,7 +619,7 @@
}
/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-u8 irq_vector[NR_IRQ_VECTORS];
+u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
int assign_irq_vector(int irq)
{
@@ -580,7 +628,7 @@
BUG_ON(irq >= NR_IRQ_VECTORS);
if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
return IO_APIC_VECTOR(irq);
- next:
+next:
current_vector += 8;
/* Skip the hypercall vector. */
@@ -621,7 +669,7 @@
irq_desc[vector].handler = &ioapic_edge_type;
}
-void __init setup_IO_APIC_irqs(void)
+static void __init setup_IO_APIC_irqs(void)
{
struct IO_APIC_route_entry entry;
int apic, pin, idx, irq, first_notcon = 1, vector;
@@ -689,6 +737,7 @@
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+ set_native_irq_info(entry.vector, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);
}
}
@@ -700,7 +749,7 @@
/*
* Set up the 8259A-master output pin:
*/
-void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
+static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin,
int vector)
{
struct IO_APIC_route_entry entry;
unsigned long flags;
@@ -734,8 +783,8 @@
* Add it to the IO-APIC irq-routing table:
*/
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
- io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+ io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
+ io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
spin_unlock_irqrestore(&ioapic_lock, flags);
enable_8259A_irq(0);
@@ -901,7 +950,8 @@
static void __init enable_IO_APIC(void)
{
union IO_APIC_reg_01 reg_01;
- int i;
+ int i8259_apic, i8259_pin;
+ int i, apic;
unsigned long flags;
for (i = 0; i < PIN_MAP_SIZE; i++) {
@@ -912,11 +962,52 @@
/*
* The number of IO-APIC IRQ registers (== #pins):
*/
- for (i = 0; i < nr_ioapics; i++) {
+ for (apic = 0; apic < nr_ioapics; apic++) {
spin_lock_irqsave(&ioapic_lock, flags);
- reg_01.raw = io_apic_read(i, 1);
+ reg_01.raw = io_apic_read(apic, 1);
spin_unlock_irqrestore(&ioapic_lock, flags);
- nr_ioapic_registers[i] = reg_01.bits.entries+1;
+ nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+ }
+ for(apic = 0; apic < nr_ioapics; apic++) {
+ int pin;
+ /* See if any of the pins is in ExtINT mode */
+ for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+ struct IO_APIC_route_entry entry;
+ spin_lock_irqsave(&ioapic_lock, flags);
+ *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
+ *(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+
+
+ /* If the interrupt line is enabled and in ExtInt mode
+ * I have found the pin where the i8259 is connected.
+ */
+ if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
+ ioapic_i8259.apic = apic;
+ ioapic_i8259.pin = pin;
+ goto found_i8259;
+ }
+ }
+ }
+ found_i8259:
+ /* Look to see what if the MP table has reported the ExtINT */
+ /* If we could not find the appropriate pin by looking at the ioapic
+ * the i8259 probably is not connected the ioapic but give the
+ * mptable a chance anyway.
+ */
+ i8259_pin = find_isa_irq_pin(0, mp_ExtINT);
+ i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
+ /* Trust the MP table if nothing is setup in the hardware */
+ if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
+ printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP
table\n");
+ ioapic_i8259.pin = i8259_pin;
+ ioapic_i8259.apic = i8259_apic;
+ }
+ /* Complain if the MP table and the hardware disagree */
+ if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin))
&&
+ (i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
+ {
+ printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
}
/*
@@ -932,10 +1023,41 @@
{
/*
* Clear the IO-APIC before rebooting:
- */
+ */
clear_IO_APIC();
- disconnect_bsp_APIC();
+ /*
+ * If the i8259 is routed through an IOAPIC
+ * Put that IOAPIC in virtual wire mode
+ * so legacy interrupts can be delivered.
+ */
+ if (ioapic_i8259.pin != -1) {
+ struct IO_APIC_route_entry entry;
+ unsigned long flags;
+
+ memset(&entry, 0, sizeof(entry));
+ entry.mask = 0; /* Enabled */
+ entry.trigger = 0; /* Edge */
+ entry.irr = 0;
+ entry.polarity = 0; /* High */
+ entry.delivery_status = 0;
+ entry.dest_mode = 0; /* Physical */
+ entry.delivery_mode = dest_ExtINT; /* ExtInt */
+ entry.vector = 0;
+ entry.dest.physical.physical_dest =
+ GET_APIC_ID(apic_read(APIC_ID));
+
+ /*
+ * Add it to the IO-APIC irq-routing table:
+ */
+ spin_lock_irqsave(&ioapic_lock, flags);
+ io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
+ *(((int *)&entry)+1));
+ io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
+ *(((int *)&entry)+0));
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ disconnect_bsp_APIC(ioapic_i8259.pin != -1);
}
/*
@@ -1248,6 +1370,8 @@
unsigned int vector, cpumask_t cpu_mask)
{
int irq = vector_to_irq(vector);
+
+ set_native_irq_info(vector, cpu_mask);
set_ioapic_affinity_irq(irq, cpu_mask);
}
@@ -1292,6 +1416,7 @@
static inline void init_IO_APIC_traps(void)
{
int irq;
+ /* Xen: This is way simpler than the Linux implementation. */
for (irq = 0; irq < 16 ; irq++)
if (IO_APIC_IRQ(irq) && !IO_APIC_VECTOR(irq))
make_8259A_irq(irq);
@@ -1339,20 +1464,21 @@
*/
static inline void unlock_ExtINT_logic(void)
{
- int pin, i;
+ int apic, pin, i;
struct IO_APIC_route_entry entry0, entry1;
unsigned char save_control, save_freq_select;
unsigned long flags;
pin = find_isa_irq_pin(8, mp_INT);
+ apic = find_isa_irq_apic(8, mp_INT);
if (pin == -1)
return;
spin_lock_irqsave(&ioapic_lock, flags);
- *(((int *)&entry0) + 1) = io_apic_read(0, 0x11 + 2 * pin);
- *(((int *)&entry0) + 0) = io_apic_read(0, 0x10 + 2 * pin);
+ *(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+ *(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
spin_unlock_irqrestore(&ioapic_lock, flags);
- clear_IO_APIC_pin(0, pin);
+ clear_IO_APIC_pin(apic, pin);
memset(&entry1, 0, sizeof(entry1));
@@ -1365,8 +1491,8 @@
entry1.vector = 0;
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
- io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
+ io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
+ io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
spin_unlock_irqrestore(&ioapic_lock, flags);
save_control = CMOS_READ(RTC_CONTROL);
@@ -1384,11 +1510,11 @@
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
- clear_IO_APIC_pin(0, pin);
+ clear_IO_APIC_pin(apic, pin);
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
- io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
+ io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
+ io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
spin_unlock_irqrestore(&ioapic_lock, flags);
}
@@ -1400,7 +1526,7 @@
*/
static inline void check_timer(void)
{
- int pin1, pin2;
+ int apic1, pin1, apic2, pin2;
int vector;
/*
@@ -1425,10 +1551,13 @@
timer_ack = 1;
enable_8259A_irq(0);
- pin1 = find_isa_irq_pin(0, mp_INT);
- pin2 = find_isa_irq_pin(0, mp_ExtINT);
-
- printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1,
pin2);
+ pin1 = find_isa_irq_pin(0, mp_INT);
+ apic1 = find_isa_irq_apic(0, mp_INT);
+ pin2 = ioapic_i8259.pin;
+ apic2 = ioapic_i8259.apic;
+
+ printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d
pin2=%d\n",
+ vector, apic1, pin1, apic2, pin2);
if (pin1 != -1) {
/*
@@ -1436,10 +1565,13 @@
*/
unmask_IO_APIC_irq(0);
if (timer_irq_works()) {
+ if (disable_timer_pin_1 > 0)
+ clear_IO_APIC_pin(apic1, pin1);
return;
}
- clear_IO_APIC_pin(0, pin1);
- printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to
IO-APIC\n");
+ clear_IO_APIC_pin(apic1, pin1);
+ printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to "
+ "IO-APIC\n");
}
printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ...
");
@@ -1448,19 +1580,19 @@
/*
* legacy devices should be connected to IO APIC #0
*/
- setup_ExtINT_IRQ0_pin(pin2, vector);
+ setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
if (timer_irq_works()) {
printk("works.\n");
if (pin1 != -1)
- replace_pin_at_irq(0, 0, pin1, 0, pin2);
+ replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
else
- add_pin_to_irq(0, 0, pin2);
+ add_pin_to_irq(0, apic2, pin2);
return;
}
/*
* Cleanup, just in case ...
*/
- clear_IO_APIC_pin(0, pin2);
+ clear_IO_APIC_pin(apic2, pin2);
}
printk(" failed.\n");
@@ -1699,6 +1831,7 @@
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
+ set_native_irq_info(entry.vector, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags);
return 0;
diff -r b9b411b50587 -r 07a892f12609 xen/arch/x86/irq.c
--- a/xen/arch/x86/irq.c Tue Feb 14 15:23:43 2006
+++ b/xen/arch/x86/irq.c Tue Feb 14 17:25:10 2006
@@ -31,8 +31,7 @@
static void disable_none(unsigned int vector) { }
static void ack_none(unsigned int vector)
{
- printk("Unexpected IRQ trap at vector %02x.\n", vector);
- ack_APIC_irq();
+ ack_bad_irq(vector);
}
#define shutdown_none disable_none
@@ -84,11 +83,11 @@
while ( desc->status & IRQ_PENDING )
{
desc->status &= ~IRQ_PENDING;
- irq_enter(smp_processor_id());
+ irq_enter();
spin_unlock_irq(&desc->lock);
action->handler(vector_to_irq(vector), action->dev_id, regs);
spin_lock_irq(&desc->lock);
- irq_exit(smp_processor_id());
+ irq_exit();
}
desc->status &= ~IRQ_INPROGRESS;
diff -r b9b411b50587 -r 07a892f12609 xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c Tue Feb 14 15:23:43 2006
+++ b/xen/arch/x86/smpboot.c Tue Feb 14 17:25:10 2006
@@ -1189,14 +1189,17 @@
set_kernel_exec((unsigned long)trampoline_base, trampoline_exec);
}
-#if 0
void __init smp_intr_init(void)
{
/*
- * The reschedule interrupt is a CPU-to-CPU reschedule-helper
- * IPI, driven by wakeup.
- */
- set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
+ * IRQ0 must be given a fixed assignment and initialized,
+ * because it's used before the IO-APIC is set up.
+ */
+ irq_vector[0] = FIRST_DEVICE_VECTOR;
+ vector_irq[FIRST_DEVICE_VECTOR] = 0;
+
+ /* IPI for event checking. */
+ set_intr_gate(EVENT_CHECK_VECTOR, event_check_interrupt);
/* IPI for invalidation */
set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
@@ -1204,4 +1207,3 @@
/* IPI for generic function call */
set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
}
-#endif
diff -r b9b411b50587 -r 07a892f12609 xen/include/asm-x86/apic.h
--- a/xen/include/asm-x86/apic.h Tue Feb 14 15:23:43 2006
+++ b/xen/include/asm-x86/apic.h Tue Feb 14 17:25:10 2006
@@ -87,7 +87,7 @@
extern int get_maxlvt(void);
extern void clear_local_APIC(void);
extern void connect_bsp_APIC (void);
-extern void disconnect_bsp_APIC (void);
+extern void disconnect_bsp_APIC (int virt_wire_setup);
extern void disable_local_APIC (void);
extern void lapic_shutdown (void);
extern int verify_local_APIC (void);
diff -r b9b411b50587 -r 07a892f12609 xen/include/asm-x86/apicdef.h
--- a/xen/include/asm-x86/apicdef.h Tue Feb 14 15:23:43 2006
+++ b/xen/include/asm-x86/apicdef.h Tue Feb 14 17:25:10 2006
@@ -87,11 +87,12 @@
#define APIC_LVT_REMOTE_IRR (1<<14)
#define APIC_INPUT_POLARITY (1<<13)
#define APIC_SEND_PENDING (1<<12)
+#define APIC_MODE_MASK 0x700
#define GET_APIC_DELIVERY_MODE(x) (((x)>>8)&0x7)
#define SET_APIC_DELIVERY_MODE(x,y)
(((x)&~0x700)|((y)<<8))
#define APIC_MODE_FIXED 0x0
#define APIC_MODE_NMI 0x4
-#define APIC_MODE_EXINT 0x7
+#define APIC_MODE_EXTINT 0x7
#define APIC_LVT1 0x360
#define APIC_LVTERR 0x370
#define APIC_TMICT 0x380
@@ -109,11 +110,10 @@
#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
-/* These limits are dictated by ES7000 hardware. */
#ifdef __i386__
- #define MAX_IO_APICS 65
+ #define MAX_IO_APICS 64
#else
- #define MAX_IO_APICS 129
+ #define MAX_IO_APICS 128
#endif
/*
diff -r b9b411b50587 -r 07a892f12609 xen/include/asm-x86/hardirq.h
--- a/xen/include/asm-x86/hardirq.h Tue Feb 14 15:23:43 2006
+++ b/xen/include/asm-x86/hardirq.h Tue Feb 14 17:25:10 2006
@@ -15,7 +15,12 @@
#define in_irq() (local_irq_count(smp_processor_id()) != 0)
-#define irq_enter(cpu) (local_irq_count(cpu)++)
-#define irq_exit(cpu) (local_irq_count(cpu)--)
+#define irq_enter() (local_irq_count(smp_processor_id())++)
+#define irq_exit() (local_irq_count(smp_processor_id())--)
+
+void ack_bad_irq(unsigned int irq);
+
+extern void apic_intr_init(void);
+extern void smp_intr_init(void);
#endif /* __ASM_HARDIRQ_H */
diff -r b9b411b50587 -r 07a892f12609 xen/include/asm-x86/irq.h
--- a/xen/include/asm-x86/irq.h Tue Feb 14 15:23:43 2006
+++ b/xen/include/asm-x86/irq.h Tue Feb 14 17:25:10 2006
@@ -24,6 +24,14 @@
#define platform_legacy_irq(irq) ((irq) < 16)
+fastcall void event_check_interrupt(void);
+fastcall void invalidate_interrupt(void);
+fastcall void call_function_interrupt(void);
+fastcall void apic_timer_interrupt(void);
+fastcall void error_interrupt(void);
+fastcall void spurious_interrupt(void);
+fastcall void thermal_interrupt(void);
+
void disable_8259A_irq(unsigned int irq);
void enable_8259A_irq(unsigned int irq);
int i8259A_irq_pending(unsigned int irq);
diff -r b9b411b50587 -r 07a892f12609 xen/include/asm-x86/x86_32/asm_defns.h
--- a/xen/include/asm-x86/x86_32/asm_defns.h Tue Feb 14 15:23:43 2006
+++ b/xen/include/asm-x86/x86_32/asm_defns.h Tue Feb 14 17:25:10 2006
@@ -58,6 +58,7 @@
asmlinkage void x(void); \
__asm__( \
"\n"__ALIGN_STR"\n" \
+ ".globl " STR(x) "\n\t" \
STR(x) ":\n\t" \
"pushl $"#v"<<16\n\t" \
STR(SAVE_ALL(a)) \
@@ -66,8 +67,6 @@
"call "STR(smp_##x)"\n\t" \
"addl $4,%esp\n\t" \
"jmp ret_from_intr\n");
-
-#define BUILD_SMP_TIMER_INTERRUPT(x,v) BUILD_SMP_INTERRUPT(x,v)
#define BUILD_COMMON_IRQ() \
__asm__( \
diff -r b9b411b50587 -r 07a892f12609 xen/include/asm-x86/x86_64/asm_defns.h
--- a/xen/include/asm-x86/x86_64/asm_defns.h Tue Feb 14 15:23:43 2006
+++ b/xen/include/asm-x86/x86_64/asm_defns.h Tue Feb 14 17:25:10 2006
@@ -65,6 +65,7 @@
asmlinkage void x(void); \
__asm__( \
"\n"__ALIGN_STR"\n" \
+ ".globl " STR(x) "\n\t" \
STR(x) ":\n\t" \
"pushq $0\n\t" \
"movl $"#v",4(%rsp)\n\t" \
@@ -72,8 +73,6 @@
"movq %rsp,%rdi\n\t" \
"callq "STR(smp_##x)"\n\t" \
"jmp ret_from_intr\n");
-
-#define BUILD_SMP_TIMER_INTERRUPT(x,v) BUILD_SMP_INTERRUPT(x,v)
#define BUILD_COMMON_IRQ() \
__asm__( \
diff -r b9b411b50587 -r 07a892f12609 xen/include/xen/config.h
--- a/xen/include/xen/config.h Tue Feb 14 15:23:43 2006
+++ b/xen/include/xen/config.h Tue Feb 14 17:25:10 2006
@@ -52,4 +52,7 @@
#define mk_unsigned_long(x) x
#endif /* !__ASSEMBLY__ */
+#define fastcall
+#define __read_mostly
+
#endif /* __XEN_CONFIG_H__ */
diff -r b9b411b50587 -r 07a892f12609 xen/include/xen/init.h
--- a/xen/include/xen/init.h Tue Feb 14 15:23:43 2006
+++ b/xen/include/xen/init.h Tue Feb 14 17:25:10 2006
@@ -100,6 +100,4 @@
#define __devexitdata __exitdata
#endif
-#define fastcall
-
#endif /* _LINUX_INIT_H */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|