ia64/xen-unstable

changeset 5071:e869b20358b1

bitkeeper revision 1.1501 (428f097bke5QSeqibAc2HvxE7ue3aA)

[PATCH] pci-ioapic-x86-64.patch

Enable PCI, IOAPIC and ACPI on domain 0 for x86-64.

This patch is based on apic.c,io_apic.c and mpparse.c on x86-64. It
applies changes analogous to the i386 files for paravirtualization.

The patch was tested on UP and DP with acpi=on and off. We did this
on a 5/10 bk tree + Jun's fixes. The latest bk tree doesn't boot yet
and needs more work.

Signed-off-by: Arun Sharma <arun.sharma@intel.com>
author arun.sharma@intel.com[kaf24]
date Sat May 21 10:12:11 2005 +0000 (2005-05-21)
parents 387d226daf5b
children 5bf66e408317
files .rootkeys linux-2.6.11-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 linux-2.6.11-xen-sparse/arch/xen/x86_64/Kconfig linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/Makefile linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/acpi/Makefile linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/apic.c linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/entry.S linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/io_apic.c linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/mpparse.c linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/setup.c linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/traps.c linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/fixmap.h linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h
line diff
     1.1 --- a/.rootkeys	Sat May 21 10:09:53 2005 +0000
     1.2 +++ b/.rootkeys	Sat May 21 10:12:11 2005 +0000
     1.3 @@ -270,6 +270,8 @@ 3f68905c5eiA-lBMQSvXLMWS1ikDEA linux-2.6
     1.4  424efaa6xahU2q85_dT-SjUJEaivfg linux-2.6.11-xen-sparse/arch/xen/x86_64/Kconfig
     1.5  424efaa6kKleWe45IrqsG8gkejgEQA linux-2.6.11-xen-sparse/arch/xen/x86_64/Makefile
     1.6  424efaa6HSyuVodl6SxFGj39vlp6MA linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/Makefile
     1.7 +428f0973_moB26LYt56xXKYCTqEdXw linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/acpi/Makefile
     1.8 +428f0973NBdgINmWOEJjoIDL73SDbQ linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/apic.c
     1.9  424efaa7bVAw3Z_q0SdFivfNVavyIg linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/asm-offsets.c
    1.10  424efaa7ddTVabh547Opf0u9vKmUXw linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/e820.c
    1.11  428868bbQust_FkSdkerMqYBWfrVKg linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/early_printk.c
    1.12 @@ -277,9 +279,11 @@ 424efaa7B_BWrAkLPJNoKk4EQY2a7w linux-2.6
    1.13  424efaa7vhgi7th5QVICjfuHmEWOkw linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/head.S
    1.14  424efaa7tiMEZSAYepwyjaNWxyXF7Q linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/head64.c
    1.15  424efaa6M6AGf53TJa2y9cl6coos0g linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/init_task.c
    1.16 +428f0973EY3nNGYatQn7IO61RHO0oQ linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/io_apic.c
    1.17  424efaa6wHXXaloZygAv6ywDb7u7nQ linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/ioport.c
    1.18  424efaa6gOkc9_uHCLgvY_DXPqh_sg linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/irq.c
    1.19  424efaa6ibN3xXEeXoxURmKfJF_CUA linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/ldt.c
    1.20 +428f09737NE-9XTvvA58TXLP0j54Uw linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/mpparse.c
    1.21  424efaa6aX4JkXAzBf4nqxRmLUfhqQ linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/pci-dma.c
    1.22  424efaa7e8nVw04q-pK8XRFaHPVx_A linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/pci-nommu.c
    1.23  424efaa7CxY9cbhqapUfqVYnD7T9LQ linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/process.c
     2.1 --- a/linux-2.6.11-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64	Sat May 21 10:09:53 2005 +0000
     2.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64	Sat May 21 10:12:11 2005 +0000
     2.3 @@ -1,7 +1,7 @@
     2.4  #
     2.5  # Automatically generated make config: don't edit
     2.6 -# Linux kernel version: 2.6.11-xen0
     2.7 -# Thu Apr 14 19:45:44 2005
     2.8 +# Linux kernel version: 2.6.11.1-xen0
     2.9 +# Tue May 10 11:07:02 2005
    2.10  #
    2.11  CONFIG_XEN=y
    2.12  CONFIG_ARCH_XEN=y
    2.13 @@ -88,8 +88,11 @@ CONFIG_X86_GOOD_APIC=y
    2.14  # CONFIG_X86_CPUID is not set
    2.15  # CONFIG_NUMA is not set
    2.16  # CONFIG_MTRR is not set
    2.17 +CONFIG_X86_LOCAL_APIC=y
    2.18 +CONFIG_X86_IO_APIC=y
    2.19  CONFIG_PCI=y
    2.20  CONFIG_PCI_DIRECT=y
    2.21 +# CONFIG_PCI_MMCONFIG is not set
    2.22  CONFIG_EARLY_PRINTK=y
    2.23  CONFIG_GENERIC_HARDIRQS=y
    2.24  CONFIG_GENERIC_IRQ_PROBE=y
    2.25 @@ -118,11 +121,6 @@ CONFIG_DUMMY_IOMMU=y
    2.26  # CONFIG_PM is not set
    2.27  
    2.28  #
    2.29 -# ACPI (Advanced Configuration and Power Interface) Support
    2.30 -#
    2.31 -# CONFIG_ACPI is not set
    2.32 -
    2.33 -#
    2.34  # CPU Frequency scaling
    2.35  #
    2.36  # CONFIG_CPU_FREQ is not set
    2.37 @@ -130,7 +128,6 @@ CONFIG_DUMMY_IOMMU=y
    2.38  #
    2.39  # Bus options (PCI etc.)
    2.40  #
    2.41 -# CONFIG_PCI_MMCONFIG is not set
    2.42  # CONFIG_UNORDERED_IO is not set
    2.43  
    2.44  #
    2.45 @@ -168,6 +165,7 @@ CONFIG_STANDALONE=y
    2.46  #
    2.47  # Plug and Play support
    2.48  #
    2.49 +# CONFIG_PNP is not set
    2.50  
    2.51  #
    2.52  # Block devices
    2.53 @@ -725,6 +723,7 @@ CONFIG_DRM_MGA=m
    2.54  CONFIG_DRM_SIS=m
    2.55  # CONFIG_MWAVE is not set
    2.56  # CONFIG_RAW_DRIVER is not set
    2.57 +# CONFIG_HPET is not set
    2.58  # CONFIG_HANGCHECK_TIMER is not set
    2.59  
    2.60  #
    2.61 @@ -796,6 +795,35 @@ CONFIG_USB_ARCH_HAS_OHCI=y
    2.62  # CONFIG_INFINIBAND is not set
    2.63  
    2.64  #
    2.65 +# Power management options
    2.66 +#
    2.67 +
    2.68 +#
    2.69 +# ACPI (Advanced Configuration and Power Interface) Support
    2.70 +#
    2.71 +CONFIG_ACPI=y
    2.72 +CONFIG_ACPI_BOOT=y
    2.73 +CONFIG_ACPI_INTERPRETER=y
    2.74 +CONFIG_ACPI_AC=m
    2.75 +CONFIG_ACPI_BATTERY=m
    2.76 +CONFIG_ACPI_BUTTON=m
    2.77 +CONFIG_ACPI_VIDEO=m
    2.78 +CONFIG_ACPI_FAN=m
    2.79 +CONFIG_ACPI_PROCESSOR=m
    2.80 +CONFIG_ACPI_THERMAL=m
    2.81 +CONFIG_ACPI_ASUS=m
    2.82 +CONFIG_ACPI_IBM=m
    2.83 +CONFIG_ACPI_TOSHIBA=m
    2.84 +CONFIG_ACPI_BLACKLIST_YEAR=0
    2.85 +# CONFIG_ACPI_DEBUG is not set
    2.86 +CONFIG_ACPI_BUS=y
    2.87 +CONFIG_ACPI_EC=y
    2.88 +CONFIG_ACPI_POWER=y
    2.89 +CONFIG_ACPI_PCI=y
    2.90 +CONFIG_ACPI_SYSTEM=y
    2.91 +# CONFIG_ACPI_CONTAINER is not set
    2.92 +
    2.93 +#
    2.94  # File systems
    2.95  #
    2.96  CONFIG_EXT2_FS=y
     3.1 --- a/linux-2.6.11-xen-sparse/arch/xen/x86_64/Kconfig	Sat May 21 10:09:53 2005 +0000
     3.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/Kconfig	Sat May 21 10:12:11 2005 +0000
     3.3 @@ -188,13 +188,13 @@ config MCA
     3.4  config EISA
     3.5  	bool
     3.6  
     3.7 -#config X86_IO_APIC
     3.8 -#	bool
     3.9 -#	default n
    3.10 +config X86_LOCAL_APIC
    3.11 +	bool
    3.12 +	default y
    3.13  
    3.14 -#config X86_LOCAL_APIC
    3.15 -#	bool
    3.16 -#	default n
    3.17 +config X86_IO_APIC
    3.18 +	bool
    3.19 +	default y
    3.20  
    3.21  config MTRR
    3.22  	bool "MTRR (Memory Type Range Register) support"
     4.1 --- a/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/Makefile	Sat May 21 10:09:53 2005 +0000
     4.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/Makefile	Sat May 21 10:12:11 2005 +0000
     4.3 @@ -12,7 +12,7 @@ obj-y	:= process.o signal.o entry.o trap
     4.4  		x8664_ksyms.o vsyscall.o \
     4.5  		setup64.o e820.o irq.o early_printk.o
     4.6  c-obj-y	:= semaphore.o i387.o sys_x86_64.o \
     4.7 -		ptrace.o quirks.o syscall.o
     4.8 +		ptrace.o quirks.o syscall.o bootflag.o
     4.9  
    4.10  i386-obj-y			:= time.o
    4.11  obj-y				+= ../../i386/kernel/timers/
    4.12 @@ -21,14 +21,15 @@ s-obj-y	:=
    4.13  
    4.14  #obj-$(CONFIG_X86_MCE)         += mce.o
    4.15  #obj-$(CONFIG_MTRR)		+= ../../i386/kernel/cpu/mtrr/
    4.16 -#obj-$(CONFIG_ACPI_BOOT)		+= acpi/
    4.17 +obj-$(CONFIG_ACPI_BOOT)		+= acpi/
    4.18  obj-$(CONFIG_X86_MSR)		+= msr.o
    4.19  obj-$(CONFIG_MICROCODE)		+= microcode.o
    4.20  obj-$(CONFIG_X86_CPUID)		+= cpuid.o
    4.21  #obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o
    4.22 -#obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o  nmi.o
    4.23 -#obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o mpparse.o \
    4.24 -#		genapic.o genapic_cluster.o genapic_flat.o
    4.25 +obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o
    4.26 +c-obj-$(CONFIG_X86_LOCAL_APIC)	+= nmi.o
    4.27 +obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o mpparse.o
    4.28 +c-obj-$(CONFIG_X86_IO_APIC)	+= genapic.o genapic_cluster.o genapic_flat.o
    4.29  #obj-$(CONFIG_PM)		+= suspend.o
    4.30  #obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend_asm.o
    4.31  #obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/acpi/Makefile	Sat May 21 10:12:11 2005 +0000
     5.3 @@ -0,0 +1,16 @@
     5.4 +i386-obj-$(CONFIG_ACPI_BOOT)		:= boot.o
     5.5 +c-obj-$(CONFIG_X86_IO_APIC)	        := earlyquirk.o
     5.6 +c-obj-$(CONFIG_ACPI_SLEEP)	        += sleep.o wakeup.o
     5.7 +
     5.8 +c-link                                  :=
     5.9 +
    5.10 +$(patsubst %.o,$(obj)/%.c,$(c-obj-y) $(c-link)):
    5.11 +	@ln -fsn $(srctree)/arch/i386/kernel/acpi/$(notdir $@) $@
    5.12 +
    5.13 +$(patsubst %.o,$(obj)/%.c,$(i386-obj-y)):
    5.14 +	ln -fsn $(srctree)/arch/xen/i386/kernel/acpi/$(notdir $@) $@
    5.15 +
    5.16 +obj-y	+= $(c-obj-y) $(s-obj-y) $(i386-obj-y)
    5.17 +
    5.18 +clean-files += $(patsubst %.o,%.c,$(c-obj-y) $(c-obj-) $(c-link))
    5.19 +clean-files += $(patsubst %.o,%.S,$(s-obj-y) $(s-obj-) $(s-link))
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/apic.c	Sat May 21 10:12:11 2005 +0000
     6.3 @@ -0,0 +1,200 @@
     6.4 +/*
     6.5 + *	Local APIC handling, local APIC timers
     6.6 + *
     6.7 + *	(c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
     6.8 + *
     6.9 + *	Fixes
    6.10 + *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
    6.11 + *					thanks to Eric Gilmore
    6.12 + *					and Rolf G. Tews
    6.13 + *					for testing these extensively.
    6.14 + *	Maciej W. Rozycki	:	Various updates and fixes.
    6.15 + *	Mikael Pettersson	:	Power Management for UP-APIC.
    6.16 + *	Pavel Machek and
    6.17 + *	Mikael Pettersson	:	PM converted to driver model.
    6.18 + */
    6.19 +
    6.20 +#include <linux/config.h>
    6.21 +#include <linux/init.h>
    6.22 +
    6.23 +#include <linux/mm.h>
    6.24 +#include <linux/irq.h>
    6.25 +#include <linux/delay.h>
    6.26 +#include <linux/bootmem.h>
    6.27 +#include <linux/smp_lock.h>
    6.28 +#include <linux/interrupt.h>
    6.29 +#include <linux/mc146818rtc.h>
    6.30 +#include <linux/kernel_stat.h>
    6.31 +#include <linux/sysdev.h>
    6.32 +
    6.33 +#include <asm/atomic.h>
    6.34 +#include <asm/smp.h>
    6.35 +#include <asm/mtrr.h>
    6.36 +#include <asm/mpspec.h>
    6.37 +#include <asm/desc.h>
    6.38 +#include <asm/arch_hooks.h>
    6.39 +#include <asm/hpet.h>
    6.40 +
    6.41 +#include "io_ports.h"
    6.42 +
    6.43 +/*
    6.44 + * Debug level
    6.45 + */
    6.46 +int apic_verbosity;
    6.47 +int disable_apic;
    6.48 +
    6.49 +void smp_local_timer_interrupt(struct pt_regs *regs)
    6.50 +{
    6.51 +	int cpu = smp_processor_id();
    6.52 +
    6.53 +	profile_tick(CPU_PROFILING, regs);
    6.54 +#if 0
    6.55 +	if (--per_cpu(prof_counter, cpu) <= 0) {
    6.56 +		/*
    6.57 +		 * The multiplier may have changed since the last time we got
    6.58 +		 * to this point as a result of the user writing to
    6.59 +		 * /proc/profile. In this case we need to adjust the APIC
    6.60 +		 * timer accordingly.
    6.61 +		 *
    6.62 +		 * Interrupts are already masked off at this point.
    6.63 +		 */
    6.64 +		per_cpu(prof_counter, cpu) = per_cpu(prof_multiplier, cpu);
    6.65 +		if (per_cpu(prof_counter, cpu) != 
    6.66 +		    per_cpu(prof_old_multiplier, cpu)) {
    6.67 +			__setup_APIC_LVTT(calibration_result/
    6.68 +					per_cpu(prof_counter, cpu));
    6.69 +			per_cpu(prof_old_multiplier, cpu) =
    6.70 +				per_cpu(prof_counter, cpu);
    6.71 +		}
    6.72 +
    6.73 +#ifdef CONFIG_SMP
    6.74 +		update_process_times(user_mode(regs));
    6.75 +#endif
    6.76 +	}
    6.77 +#endif
    6.78 +
    6.79 +	/*
    6.80 +	 * We take the 'long' return path, and there every subsystem
    6.81 +	 * grabs the appropriate locks (kernel lock/ irq lock).
    6.82 +	 *
    6.83 +	 * we might want to decouple profiling from the 'long path',
    6.84 +	 * and do the profiling totally in assembly.
    6.85 +	 *
    6.86 +	 * Currently this isn't too much of an issue (performance wise),
    6.87 +	 * we can take more than 100K local irqs per second on a 100 MHz P5.
    6.88 +	 */
    6.89 +}
    6.90 +
    6.91 +/*
    6.92 + * Local APIC timer interrupt. This is the most natural way for doing
    6.93 + * local interrupts, but local timer interrupts can be emulated by
    6.94 + * broadcast interrupts too. [in case the hw doesn't support APIC timers]
    6.95 + *
    6.96 + * [ if a single-CPU system runs an SMP kernel then we call the local
    6.97 + *   interrupt as well. Thus we cannot inline the local irq ... ]
    6.98 + */
    6.99 +void smp_apic_timer_interrupt(struct pt_regs *regs)
   6.100 +{
   6.101 +	/*
   6.102 +	 * the NMI deadlock-detector uses this.
   6.103 +	 */
   6.104 +	add_pda(apic_timer_irqs, 1);
   6.105 +
   6.106 +	/*
   6.107 +	 * NOTE! We'd better ACK the irq immediately,
   6.108 +	 * because timer handling can be slow.
   6.109 +	 */
   6.110 +	ack_APIC_irq();
   6.111 +	/*
   6.112 +	 * update_process_times() expects us to have done irq_enter().
   6.113 +	 * Besides, if we don't timer interrupts ignore the global
   6.114 +	 * interrupt lock, which is the WrongThing (tm) to do.
   6.115 +	 */
   6.116 +	irq_enter();
   6.117 +	smp_local_timer_interrupt(regs);
   6.118 +	irq_exit();
   6.119 +}
   6.120 +
   6.121 +/*
   6.122 + * This interrupt should _never_ happen with our APIC/SMP architecture
   6.123 + */
   6.124 +asmlinkage void smp_spurious_interrupt(void)
   6.125 +{
   6.126 +	unsigned int v;
   6.127 +	irq_enter();
   6.128 +	/*
   6.129 +	 * Check if this really is a spurious interrupt and ACK it
   6.130 +	 * if it is a vectored one.  Just in case...
   6.131 +	 * Spurious interrupts should not be ACKed.
   6.132 +	 */
   6.133 +	v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
   6.134 +	if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
   6.135 +		ack_APIC_irq();
   6.136 +
   6.137 +#if 0
   6.138 +	static unsigned long last_warning; 
   6.139 +	static unsigned long skipped; 
   6.140 +
   6.141 +	/* see sw-dev-man vol 3, chapter 7.4.13.5 */
   6.142 +	if (time_before(last_warning+30*HZ,jiffies)) { 
   6.143 +		printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n",
   6.144 +		       smp_processor_id(), skipped);
   6.145 +		last_warning = jiffies; 
   6.146 +		skipped = 0;
   6.147 +	} else { 
   6.148 +		skipped++; 
   6.149 +	} 
   6.150 +#endif 
   6.151 +	irq_exit();
   6.152 +}
   6.153 +
   6.154 +/*
   6.155 + * This interrupt should never happen with our APIC/SMP architecture
   6.156 + */
   6.157 +
   6.158 +asmlinkage void smp_error_interrupt(void)
   6.159 +{
   6.160 +	unsigned int v, v1;
   6.161 +
   6.162 +	irq_enter();
   6.163 +	/* First tickle the hardware, only then report what went on. -- REW */
   6.164 +	v = apic_read(APIC_ESR);
   6.165 +	apic_write(APIC_ESR, 0);
   6.166 +	v1 = apic_read(APIC_ESR);
   6.167 +	ack_APIC_irq();
   6.168 +	atomic_inc(&irq_err_count);
   6.169 +
   6.170 +	/* Here is what the APIC error bits mean:
   6.171 +	   0: Send CS error
   6.172 +	   1: Receive CS error
   6.173 +	   2: Send accept error
   6.174 +	   3: Receive accept error
   6.175 +	   4: Reserved
   6.176 +	   5: Send illegal vector
   6.177 +	   6: Received illegal vector
   6.178 +	   7: Illegal register address
   6.179 +	*/
   6.180 +	printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
   6.181 +	        smp_processor_id(), v , v1);
   6.182 +	irq_exit();
   6.183 +}
   6.184 +
   6.185 +int get_physical_broadcast(void)
   6.186 +{
   6.187 +        return 0xff;
   6.188 +}
   6.189 +
   6.190 +/*
   6.191 + * This initializes the IO-APIC and APIC hardware if this is
   6.192 + * a UP kernel.
   6.193 + */
   6.194 +int __init APIC_init_uniprocessor (void)
   6.195 +{
   6.196 +#ifdef CONFIG_X86_IO_APIC
   6.197 +	if (smp_found_config)
   6.198 +		if (!skip_ioapic_setup && nr_ioapics)
   6.199 +			setup_IO_APIC();
   6.200 +#endif
   6.201 +
   6.202 +	return 0;
   6.203 +}
     7.1 --- a/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/entry.S	Sat May 21 10:09:53 2005 +0000
     7.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/entry.S	Sat May 21 10:12:11 2005 +0000
     7.3 @@ -48,6 +48,7 @@
     7.4  #include <asm/errno.h>
     7.5  #include <asm-xen/xen-public/arch-x86_64.h>
     7.6  
     7.7 +#include "irq_vectors.h"
     7.8  
     7.9  EVENT_MASK      = (CS+4)
    7.10  VGCF_IN_SYSCALL = (1<<8)
    7.11 @@ -584,7 +585,7 @@ retint_kernel:
    7.12  	.macro apicinterrupt num,func
    7.13  	pushq $\num-256
    7.14  	interrupt \func
    7.15 -	jmp ret_from_intr
    7.16 +	jmp error_entry
    7.17  	CFI_ENDPROC
    7.18  	.endm
    7.19  
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/io_apic.c	Sat May 21 10:12:11 2005 +0000
     8.3 @@ -0,0 +1,2051 @@
     8.4 +/*
     8.5 + *	Intel IO-APIC support for multi-Pentium hosts.
     8.6 + *
     8.7 + *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
     8.8 + *
     8.9 + *	Many thanks to Stig Venaas for trying out countless experimental
    8.10 + *	patches and reporting/debugging problems patiently!
    8.11 + *
    8.12 + *	(c) 1999, Multiple IO-APIC support, developed by
    8.13 + *	Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
    8.14 + *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
    8.15 + *	further tested and cleaned up by Zach Brown <zab@redhat.com>
    8.16 + *	and Ingo Molnar <mingo@redhat.com>
    8.17 + *
    8.18 + *	Fixes
    8.19 + *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
    8.20 + *					thanks to Eric Gilmore
    8.21 + *					and Rolf G. Tews
    8.22 + *					for testing these extensively
    8.23 + *	Paul Diefenbaugh	:	Added full ACPI support
    8.24 + */
    8.25 +
    8.26 +#include <linux/mm.h>
    8.27 +#include <linux/irq.h>
    8.28 +#include <linux/interrupt.h>
    8.29 +#include <linux/init.h>
    8.30 +#include <linux/delay.h>
    8.31 +#include <linux/sched.h>
    8.32 +#include <linux/config.h>
    8.33 +#include <linux/smp_lock.h>
    8.34 +#include <linux/mc146818rtc.h>
    8.35 +#include <linux/acpi.h>
    8.36 +#include <linux/sysdev.h>
    8.37 +
    8.38 +#include <asm/io.h>
    8.39 +#include <asm/smp.h>
    8.40 +#include <asm/desc.h>
    8.41 +#include <asm/proto.h>
    8.42 +#include <asm/mach_apic.h>
    8.43 +
    8.44 +#define __apicdebuginit  __init
    8.45 +
    8.46 +int sis_apic_bug; /* not actually supported, dummy for compile */
    8.47 +
    8.48 +static DEFINE_SPINLOCK(ioapic_lock);
    8.49 +
    8.50 +/*
    8.51 + * # of IRQ routing registers
    8.52 + */
    8.53 +int nr_ioapic_registers[MAX_IO_APICS];
    8.54 +
    8.55 +/*
    8.56 + * Rough estimation of how many shared IRQs there are, can
    8.57 + * be changed anytime.
    8.58 + */
    8.59 +#define MAX_PLUS_SHARED_IRQS NR_IRQS
    8.60 +#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
    8.61 +
    8.62 +/*
    8.63 + * This is performance-critical, we want to do it O(1)
    8.64 + *
    8.65 + * the indexing order of this array favors 1:1 mappings
    8.66 + * between pins and IRQs.
    8.67 + */
    8.68 +
    8.69 +static struct irq_pin_list {
    8.70 +	short apic, pin, next;
    8.71 +} irq_2_pin[PIN_MAP_SIZE];
    8.72 +
    8.73 +int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
    8.74 +#ifdef CONFIG_PCI_MSI
    8.75 +#define vector_to_irq(vector) 	\
    8.76 +	(platform_legacy_irq(vector) ? vector : vector_irq[vector])
    8.77 +#else
    8.78 +#define vector_to_irq(vector)	(vector)
    8.79 +#endif
    8.80 +
    8.81 +#ifdef CONFIG_XEN
    8.82 +
    8.83 +#include <asm-xen/xen-public/xen.h>
    8.84 +#include <asm-xen/xen-public/physdev.h>
    8.85 +
    8.86 +/* Fake i8259 */
    8.87 +#define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
    8.88 +#define disable_8259A_irq(_irq)  ((void)0)
    8.89 +#define i8259A_irq_pending(_irq) (0)
    8.90 +
    8.91 +unsigned long io_apic_irqs;
    8.92 +
    8.93 +static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg)
    8.94 +{
    8.95 +	physdev_op_t op;
    8.96 +	int ret;
    8.97 +
    8.98 +	op.cmd = PHYSDEVOP_APIC_READ;
    8.99 +	op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
   8.100 +	op.u.apic_op.offset = reg;
   8.101 +	ret = HYPERVISOR_physdev_op(&op);
   8.102 +	if (ret)
   8.103 +		return ret;
   8.104 +	return op.u.apic_op.value;
   8.105 +}
   8.106 +
   8.107 +static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
   8.108 +{
   8.109 +	physdev_op_t op;
   8.110 +
   8.111 +	op.cmd = PHYSDEVOP_APIC_WRITE;
   8.112 +	op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
   8.113 +	op.u.apic_op.offset = reg;
   8.114 +	op.u.apic_op.value = value;
   8.115 +	HYPERVISOR_physdev_op(&op);
   8.116 +}
   8.117 +
   8.118 +#define io_apic_read(a,r)    xen_io_apic_read(a,r)
   8.119 +#define io_apic_write(a,r,v) xen_io_apic_write(a,r,v)
   8.120 +
   8.121 +#define clear_IO_APIC() ((void)0)
   8.122 +
   8.123 +#endif /* !CONFIG_XEN */
   8.124 +
   8.125 +/*
   8.126 + * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
   8.127 + * shared ISA-space IRQs, so we have to support them. We are super
   8.128 + * fast in the common case, and fast for shared ISA-space IRQs.
   8.129 + */
   8.130 +static void add_pin_to_irq(unsigned int irq, int apic, int pin)
   8.131 +{
   8.132 +	static int first_free_entry = NR_IRQS;
   8.133 +	struct irq_pin_list *entry = irq_2_pin + irq;
   8.134 +
   8.135 +	while (entry->next)
   8.136 +		entry = irq_2_pin + entry->next;
   8.137 +
   8.138 +	if (entry->pin != -1) {
   8.139 +		entry->next = first_free_entry;
   8.140 +		entry = irq_2_pin + entry->next;
   8.141 +		if (++first_free_entry >= PIN_MAP_SIZE)
   8.142 +			panic("io_apic.c: whoops");
   8.143 +	}
   8.144 +	entry->apic = apic;
   8.145 +	entry->pin = pin;
   8.146 +}
   8.147 +
   8.148 +#ifndef CONFIG_XEN
   8.149 +#define __DO_ACTION(R, ACTION, FINAL)					\
   8.150 +									\
   8.151 +{									\
   8.152 +	int pin;							\
   8.153 +	struct irq_pin_list *entry = irq_2_pin + irq;			\
   8.154 +									\
   8.155 +	for (;;) {							\
   8.156 +		unsigned int reg;					\
   8.157 +		pin = entry->pin;					\
   8.158 +		if (pin == -1)						\
   8.159 +			break;						\
   8.160 +		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
   8.161 +		reg ACTION;						\
   8.162 +		io_apic_modify(entry->apic, reg);			\
   8.163 +		if (!entry->next)					\
   8.164 +			break;						\
   8.165 +		entry = irq_2_pin + entry->next;			\
   8.166 +	}								\
   8.167 +	FINAL;								\
   8.168 +}
   8.169 +
   8.170 +#define DO_ACTION(name,R,ACTION, FINAL)					\
   8.171 +									\
   8.172 +	static void name##_IO_APIC_irq (unsigned int irq)		\
   8.173 +	__DO_ACTION(R, ACTION, FINAL)
   8.174 +
   8.175 +DO_ACTION( __mask,             0, |= 0x00010000, io_apic_sync(entry->apic) )
   8.176 +						/* mask = 1 */
   8.177 +DO_ACTION( __unmask,           0, &= 0xfffeffff, )
   8.178 +						/* mask = 0 */
   8.179 +
   8.180 +static void mask_IO_APIC_irq (unsigned int irq)
   8.181 +{
   8.182 +	unsigned long flags;
   8.183 +
   8.184 +	spin_lock_irqsave(&ioapic_lock, flags);
   8.185 +	__mask_IO_APIC_irq(irq);
   8.186 +	spin_unlock_irqrestore(&ioapic_lock, flags);
   8.187 +}
   8.188 +
   8.189 +static void unmask_IO_APIC_irq (unsigned int irq)
   8.190 +{
   8.191 +	unsigned long flags;
   8.192 +
   8.193 +	spin_lock_irqsave(&ioapic_lock, flags);
   8.194 +	__unmask_IO_APIC_irq(irq);
   8.195 +	spin_unlock_irqrestore(&ioapic_lock, flags);
   8.196 +}
   8.197 +
   8.198 +void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
   8.199 +{
   8.200 +	struct IO_APIC_route_entry entry;
   8.201 +	unsigned long flags;
   8.202 +
   8.203 +	/* Check delivery_mode to be sure we're not clearing an SMI pin */
   8.204 +	spin_lock_irqsave(&ioapic_lock, flags);
   8.205 +	*(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
   8.206 +	*(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
   8.207 +	spin_unlock_irqrestore(&ioapic_lock, flags);
   8.208 +	if (entry.delivery_mode == dest_SMI)
   8.209 +		return;
   8.210 +	/*
   8.211 +	 * Disable it in the IO-APIC irq-routing table:
   8.212 +	 */
   8.213 +	memset(&entry, 0, sizeof(entry));
   8.214 +	entry.mask = 1;
   8.215 +	spin_lock_irqsave(&ioapic_lock, flags);
   8.216 +	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
   8.217 +	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
   8.218 +	spin_unlock_irqrestore(&ioapic_lock, flags);
   8.219 +}
   8.220 +
   8.221 +static void clear_IO_APIC (void)
   8.222 +{
   8.223 +	int apic, pin;
   8.224 +
   8.225 +	for (apic = 0; apic < nr_ioapics; apic++)
   8.226 +		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
   8.227 +			clear_IO_APIC_pin(apic, pin);
   8.228 +}
   8.229 +
   8.230 +#endif /* !CONFIG_XEN */
   8.231 +
   8.232 +/*
   8.233 + * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
   8.234 + * specific CPU-side IRQs.
   8.235 + */
   8.236 +
   8.237 +#define MAX_PIRQS 8
   8.238 +int pirq_entries [MAX_PIRQS];
   8.239 +int pirqs_enabled;
   8.240 +int skip_ioapic_setup;
   8.241 +int ioapic_force;
   8.242 +
   8.243 +/* dummy parsing: see setup.c */
   8.244 +
   8.245 +static int __init disable_ioapic_setup(char *str)
   8.246 +{
   8.247 +	skip_ioapic_setup = 1;
   8.248 +	return 1;
   8.249 +}
   8.250 +
   8.251 +static int __init enable_ioapic_setup(char *str)
   8.252 +{
   8.253 +	ioapic_force = 1;
   8.254 +	skip_ioapic_setup = 0;
   8.255 +	return 1;
   8.256 +}
   8.257 +
   8.258 +
   8.259 +__setup("noapic", disable_ioapic_setup);
   8.260 +__setup("apic", enable_ioapic_setup);
   8.261 +
   8.262 +
   8.263 +#include <asm/pci-direct.h>
   8.264 +#include <linux/pci_ids.h>
   8.265 +#include <linux/pci.h>
   8.266 +
   8.267 +/* Temporary Hack. Nvidia and VIA boards currently only work with IO-APIC
   8.268 +   off. Check for an Nvidia or VIA PCI bridge and turn it off.
   8.269 +   Use pci direct infrastructure because this runs before the PCI subsystem. 
   8.270 +
   8.271 +   Can be overwritten with "apic"
   8.272 +
   8.273 +   And another hack to disable the IOMMU on VIA chipsets.
   8.274 +
   8.275 +   Kludge-O-Rama. */
   8.276 +void __init check_ioapic(void) 
   8.277 +{ 
   8.278 +	int num,slot,func; 
   8.279 +	if (ioapic_force) 
   8.280 +		return; 
   8.281 +
   8.282 +	/* Poor man's PCI discovery */
   8.283 +	for (num = 0; num < 32; num++) { 
   8.284 +		for (slot = 0; slot < 32; slot++) { 
   8.285 +			for (func = 0; func < 8; func++) { 
   8.286 +				u32 class;
   8.287 +				u32 vendor;
   8.288 +				u8 type;
   8.289 +				class = read_pci_config(num,slot,func,
   8.290 +							PCI_CLASS_REVISION);
   8.291 +				if (class == 0xffffffff)
   8.292 +					break; 
   8.293 +
   8.294 +		       		if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
   8.295 +					continue; 
   8.296 +
   8.297 +				vendor = read_pci_config(num, slot, func, 
   8.298 +							 PCI_VENDOR_ID);
   8.299 +				vendor &= 0xffff;
   8.300 +				switch (vendor) { 
   8.301 +				case PCI_VENDOR_ID_VIA:
   8.302 +#ifdef CONFIG_GART_IOMMU
   8.303 +					if ((end_pfn >= (0xffffffff>>PAGE_SHIFT) ||
   8.304 +					     force_iommu) &&
   8.305 +					    !iommu_aperture_allowed) {
   8.306 +						printk(KERN_INFO
   8.307 +    "Looks like a VIA chipset. Disabling IOMMU. Overwrite with \"iommu=allowed\"\n");
   8.308 +						iommu_aperture_disabled = 1;
   8.309 +					}
   8.310 +#endif
   8.311 +					return;
   8.312 +				case PCI_VENDOR_ID_NVIDIA:
   8.313 +#ifdef CONFIG_ACPI
   8.314 +					/* All timer overrides on Nvidia
   8.315 +				           seem to be wrong. Skip them. */
   8.316 +					acpi_skip_timer_override = 1;
   8.317 +					printk(KERN_INFO 
   8.318 +	     "Nvidia board detected. Ignoring ACPI timer override.\n");
   8.319 +#endif
   8.320 +					/* RED-PEN skip them on mptables too? */
   8.321 +					return;
   8.322 +				} 
   8.323 +
   8.324 +				/* No multi-function device? */
   8.325 +				type = read_pci_config_byte(num,slot,func,
   8.326 +							    PCI_HEADER_TYPE);
   8.327 +				if (!(type & 0x80))
   8.328 +					break;
   8.329 +			} 
   8.330 +		}
   8.331 +	}
   8.332 +} 
   8.333 +
   8.334 +static int __init ioapic_pirq_setup(char *str)
   8.335 +{
   8.336 +	int i, max;
   8.337 +	int ints[MAX_PIRQS+1];
   8.338 +
   8.339 +	get_options(str, ARRAY_SIZE(ints), ints);
   8.340 +
   8.341 +	for (i = 0; i < MAX_PIRQS; i++)
   8.342 +		pirq_entries[i] = -1;
   8.343 +
   8.344 +	pirqs_enabled = 1;
   8.345 +	apic_printk(APIC_VERBOSE, "PIRQ redirection, working around broken MP-BIOS.\n");
   8.346 +	max = MAX_PIRQS;
   8.347 +	if (ints[0] < MAX_PIRQS)
   8.348 +		max = ints[0];
   8.349 +
   8.350 +	for (i = 0; i < max; i++) {
   8.351 +		apic_printk(APIC_VERBOSE, "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
   8.352 +		/*
   8.353 +		 * PIRQs are mapped upside down, usually.
   8.354 +		 */
   8.355 +		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
   8.356 +	}
   8.357 +	return 1;
   8.358 +}
   8.359 +
   8.360 +__setup("pirq=", ioapic_pirq_setup);
   8.361 +
   8.362 +/*
   8.363 + * Find the IRQ entry number of a certain pin.
   8.364 + */
   8.365 +static int find_irq_entry(int apic, int pin, int type)
   8.366 +{
   8.367 +	int i;
   8.368 +
   8.369 +	for (i = 0; i < mp_irq_entries; i++)
   8.370 +		if (mp_irqs[i].mpc_irqtype == type &&
   8.371 +		    (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid ||
   8.372 +		     mp_irqs[i].mpc_dstapic == MP_APIC_ALL) &&
   8.373 +		    mp_irqs[i].mpc_dstirq == pin)
   8.374 +			return i;
   8.375 +
   8.376 +	return -1;
   8.377 +}
   8.378 +
   8.379 +#ifndef CONFIG_XEN
   8.380 +/*
   8.381 + * Find the pin to which IRQ[irq] (ISA) is connected
   8.382 + */
   8.383 +static int __init find_isa_irq_pin(int irq, int type)
   8.384 +{
   8.385 +	int i;
   8.386 +
   8.387 +	for (i = 0; i < mp_irq_entries; i++) {
   8.388 +		int lbus = mp_irqs[i].mpc_srcbus;
   8.389 +
   8.390 +		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
   8.391 +		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
   8.392 +		     mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
   8.393 +		    (mp_irqs[i].mpc_irqtype == type) &&
   8.394 +		    (mp_irqs[i].mpc_srcbusirq == irq))
   8.395 +
   8.396 +			return mp_irqs[i].mpc_dstirq;
   8.397 +	}
   8.398 +	return -1;
   8.399 +}
   8.400 +#endif
   8.401 +
   8.402 +/*
   8.403 + * Find a specific PCI IRQ entry.
   8.404 + * Not an __init, possibly needed by modules
   8.405 + */
   8.406 +static int pin_2_irq(int idx, int apic, int pin);
   8.407 +
   8.408 +int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
   8.409 +{
   8.410 +	int apic, i, best_guess = -1;
   8.411 +
   8.412 +	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
   8.413 +		bus, slot, pin);
   8.414 +	if (mp_bus_id_to_pci_bus[bus] == -1) {
   8.415 +		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
   8.416 +		return -1;
   8.417 +	}
   8.418 +	for (i = 0; i < mp_irq_entries; i++) {
   8.419 +		int lbus = mp_irqs[i].mpc_srcbus;
   8.420 +
   8.421 +		for (apic = 0; apic < nr_ioapics; apic++)
   8.422 +			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic ||
   8.423 +			    mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
   8.424 +				break;
   8.425 +
   8.426 +		if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
   8.427 +		    !mp_irqs[i].mpc_irqtype &&
   8.428 +		    (bus == lbus) &&
   8.429 +		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
   8.430 +			int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
   8.431 +
   8.432 +			if (!(apic || IO_APIC_IRQ(irq)))
   8.433 +				continue;
   8.434 +
   8.435 +			if (pin == (mp_irqs[i].mpc_srcbusirq & 3))
   8.436 +				return irq;
   8.437 +			/*
   8.438 +			 * Use the first all-but-pin matching entry as a
   8.439 +			 * best-guess fuzzy result for broken mptables.
   8.440 +			 */
   8.441 +			if (best_guess < 0)
   8.442 +				best_guess = irq;
   8.443 +		}
   8.444 +	}
   8.445 +	return best_guess;
   8.446 +}
   8.447 +
   8.448 +/*
   8.449 + * EISA Edge/Level control register, ELCR
   8.450 + */
   8.451 +static int EISA_ELCR(unsigned int irq)
   8.452 +{
   8.453 +	if (irq < 16) {
   8.454 +		unsigned int port = 0x4d0 + (irq >> 3);
   8.455 +		return (inb(port) >> (irq & 7)) & 1;
   8.456 +	}
   8.457 +	apic_printk(APIC_VERBOSE, "Broken MPtable reports ISA irq %d\n", irq);
   8.458 +	return 0;
   8.459 +}
   8.460 +
   8.461 +/* EISA interrupts are always polarity zero and can be edge or level
   8.462 + * trigger depending on the ELCR value.  If an interrupt is listed as
   8.463 + * EISA conforming in the MP table, that means its trigger type must
   8.464 + * be read in from the ELCR */
   8.465 +
   8.466 +#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))
   8.467 +#define default_EISA_polarity(idx)	(0)
   8.468 +
   8.469 +/* ISA interrupts are always polarity zero edge triggered,
   8.470 + * when listed as conforming in the MP table. */
   8.471 +
   8.472 +#define default_ISA_trigger(idx)	(0)
   8.473 +#define default_ISA_polarity(idx)	(0)
   8.474 +
   8.475 +/* PCI interrupts are always polarity one level triggered,
   8.476 + * when listed as conforming in the MP table. */
   8.477 +
   8.478 +#define default_PCI_trigger(idx)	(1)
   8.479 +#define default_PCI_polarity(idx)	(1)
   8.480 +
   8.481 +/* MCA interrupts are always polarity zero level triggered,
   8.482 + * when listed as conforming in the MP table. */
   8.483 +
   8.484 +#define default_MCA_trigger(idx)	(1)
   8.485 +#define default_MCA_polarity(idx)	(0)
   8.486 +
   8.487 +static int __init MPBIOS_polarity(int idx)
   8.488 +{
   8.489 +	int bus = mp_irqs[idx].mpc_srcbus;
   8.490 +	int polarity;
   8.491 +
   8.492 +	/*
   8.493 +	 * Determine IRQ line polarity (high active or low active):
   8.494 +	 */
   8.495 +	switch (mp_irqs[idx].mpc_irqflag & 3)
   8.496 +	{
   8.497 +		case 0: /* conforms, ie. bus-type dependent polarity */
   8.498 +		{
   8.499 +			switch (mp_bus_id_to_type[bus])
   8.500 +			{
   8.501 +				case MP_BUS_ISA: /* ISA pin */
   8.502 +				{
   8.503 +					polarity = default_ISA_polarity(idx);
   8.504 +					break;
   8.505 +				}
   8.506 +				case MP_BUS_EISA: /* EISA pin */
   8.507 +				{
   8.508 +					polarity = default_EISA_polarity(idx);
   8.509 +					break;
   8.510 +				}
   8.511 +				case MP_BUS_PCI: /* PCI pin */
   8.512 +				{
   8.513 +					polarity = default_PCI_polarity(idx);
   8.514 +					break;
   8.515 +				}
   8.516 +				case MP_BUS_MCA: /* MCA pin */
   8.517 +				{
   8.518 +					polarity = default_MCA_polarity(idx);
   8.519 +					break;
   8.520 +				}
   8.521 +				default:
   8.522 +				{
   8.523 +					printk(KERN_WARNING "broken BIOS!!\n");
   8.524 +					polarity = 1;
   8.525 +					break;
   8.526 +				}
   8.527 +			}
   8.528 +			break;
   8.529 +		}
   8.530 +		case 1: /* high active */
   8.531 +		{
   8.532 +			polarity = 0;
   8.533 +			break;
   8.534 +		}
   8.535 +		case 2: /* reserved */
   8.536 +		{
   8.537 +			printk(KERN_WARNING "broken BIOS!!\n");
   8.538 +			polarity = 1;
   8.539 +			break;
   8.540 +		}
   8.541 +		case 3: /* low active */
   8.542 +		{
   8.543 +			polarity = 1;
   8.544 +			break;
   8.545 +		}
   8.546 +		default: /* invalid */
   8.547 +		{
   8.548 +			printk(KERN_WARNING "broken BIOS!!\n");
   8.549 +			polarity = 1;
   8.550 +			break;
   8.551 +		}
   8.552 +	}
   8.553 +	return polarity;
   8.554 +}
   8.555 +
   8.556 +static int MPBIOS_trigger(int idx)
   8.557 +{
   8.558 +	int bus = mp_irqs[idx].mpc_srcbus;
   8.559 +	int trigger;
   8.560 +
   8.561 +	/*
   8.562 +	 * Determine IRQ trigger mode (edge or level sensitive):
   8.563 +	 */
   8.564 +	switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)
   8.565 +	{
   8.566 +		case 0: /* conforms, ie. bus-type dependent */
   8.567 +		{
   8.568 +			switch (mp_bus_id_to_type[bus])
   8.569 +			{
   8.570 +				case MP_BUS_ISA: /* ISA pin */
   8.571 +				{
   8.572 +					trigger = default_ISA_trigger(idx);
   8.573 +					break;
   8.574 +				}
   8.575 +				case MP_BUS_EISA: /* EISA pin */
   8.576 +				{
   8.577 +					trigger = default_EISA_trigger(idx);
   8.578 +					break;
   8.579 +				}
   8.580 +				case MP_BUS_PCI: /* PCI pin */
   8.581 +				{
   8.582 +					trigger = default_PCI_trigger(idx);
   8.583 +					break;
   8.584 +				}
   8.585 +				case MP_BUS_MCA: /* MCA pin */
   8.586 +				{
   8.587 +					trigger = default_MCA_trigger(idx);
   8.588 +					break;
   8.589 +				}
   8.590 +				default:
   8.591 +				{
   8.592 +					printk(KERN_WARNING "broken BIOS!!\n");
   8.593 +					trigger = 1;
   8.594 +					break;
   8.595 +				}
   8.596 +			}
   8.597 +			break;
   8.598 +		}
   8.599 +		case 1: /* edge */
   8.600 +		{
   8.601 +			trigger = 0;
   8.602 +			break;
   8.603 +		}
   8.604 +		case 2: /* reserved */
   8.605 +		{
   8.606 +			printk(KERN_WARNING "broken BIOS!!\n");
   8.607 +			trigger = 1;
   8.608 +			break;
   8.609 +		}
   8.610 +		case 3: /* level */
   8.611 +		{
   8.612 +			trigger = 1;
   8.613 +			break;
   8.614 +		}
   8.615 +		default: /* invalid */
   8.616 +		{
   8.617 +			printk(KERN_WARNING "broken BIOS!!\n");
   8.618 +			trigger = 0;
   8.619 +			break;
   8.620 +		}
   8.621 +	}
   8.622 +	return trigger;
   8.623 +}
   8.624 +
   8.625 +static inline int irq_polarity(int idx)
   8.626 +{
   8.627 +	return MPBIOS_polarity(idx);
   8.628 +}
   8.629 +
   8.630 +static inline int irq_trigger(int idx)
   8.631 +{
   8.632 +	return MPBIOS_trigger(idx);
   8.633 +}
   8.634 +
   8.635 +static int pin_2_irq(int idx, int apic, int pin)
   8.636 +{
   8.637 +	int irq, i;
   8.638 +	int bus = mp_irqs[idx].mpc_srcbus;
   8.639 +
   8.640 +	/*
   8.641 +	 * Debugging check, we are in big trouble if this message pops up!
   8.642 +	 */
   8.643 +	if (mp_irqs[idx].mpc_dstirq != pin)
   8.644 +		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
   8.645 +
   8.646 +	switch (mp_bus_id_to_type[bus])
   8.647 +	{
   8.648 +		case MP_BUS_ISA: /* ISA pin */
   8.649 +		case MP_BUS_EISA:
   8.650 +		case MP_BUS_MCA:
   8.651 +		{
   8.652 +			irq = mp_irqs[idx].mpc_srcbusirq;
   8.653 +			break;
   8.654 +		}
   8.655 +		case MP_BUS_PCI: /* PCI pin */
   8.656 +		{
   8.657 +			/*
   8.658 +			 * PCI IRQs are mapped in order
   8.659 +			 */
   8.660 +			i = irq = 0;
   8.661 +			while (i < apic)
   8.662 +				irq += nr_ioapic_registers[i++];
   8.663 +			irq += pin;
   8.664 +			break;
   8.665 +		}
   8.666 +		default:
   8.667 +		{
   8.668 +			printk(KERN_ERR "unknown bus type %d.\n",bus); 
   8.669 +			irq = 0;
   8.670 +			break;
   8.671 +		}
   8.672 +	}
   8.673 +
   8.674 +	/*
   8.675 +	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
   8.676 +	 */
   8.677 +	if ((pin >= 16) && (pin <= 23)) {
   8.678 +		if (pirq_entries[pin-16] != -1) {
   8.679 +			if (!pirq_entries[pin-16]) {
   8.680 +				apic_printk(APIC_VERBOSE, "disabling PIRQ%d\n", pin-16);
   8.681 +			} else {
   8.682 +				irq = pirq_entries[pin-16];
   8.683 +				apic_printk(APIC_VERBOSE, "using PIRQ%d -> IRQ %d\n",
   8.684 +						pin-16, irq);
   8.685 +			}
   8.686 +		}
   8.687 +	}
   8.688 +	return irq;
   8.689 +}
   8.690 +
   8.691 +static inline int IO_APIC_irq_trigger(int irq)
   8.692 +{
   8.693 +	int apic, idx, pin;
   8.694 +
   8.695 +	for (apic = 0; apic < nr_ioapics; apic++) {
   8.696 +		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
   8.697 +			idx = find_irq_entry(apic,pin,mp_INT);
   8.698 +			if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))
   8.699 +				return irq_trigger(idx);
   8.700 +		}
   8.701 +	}
   8.702 +	/*
   8.703 +	 * nonexistent IRQs are edge default
   8.704 +	 */
   8.705 +	return 0;
   8.706 +}
   8.707 +
   8.708 +/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
   8.709 +u8 irq_vector[NR_IRQ_VECTORS];
   8.710 +
   8.711 +int assign_irq_vector(int irq)
   8.712 +{
   8.713 +	static int current_vector = FIRST_DEVICE_VECTOR;
   8.714 +	physdev_op_t op;
   8.715 +  
   8.716 +  	BUG_ON(irq >= NR_IRQ_VECTORS);
   8.717 +  	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
   8.718 +  		return IO_APIC_VECTOR(irq);
   8.719 +
   8.720 +	op.cmd = PHYSDEVOP_ASSIGN_VECTOR;
   8.721 +	op.u.irq_op.irq = irq;
   8.722 +	if (HYPERVISOR_physdev_op(&op))
   8.723 +		return -ENOSPC;
   8.724 +	current_vector = op.u.irq_op.vector;
   8.725 +
   8.726 +	vector_irq[current_vector] = irq;
   8.727 +	if (irq != AUTO_ASSIGN)
   8.728 +		IO_APIC_VECTOR(irq) = current_vector;
   8.729 +
   8.730 +	return current_vector;
   8.731 +}
   8.732 +
   8.733 +extern void (*interrupt[NR_IRQS])(void);
   8.734 +#ifndef CONFIG_XEN
   8.735 +static struct hw_interrupt_type ioapic_level_type;
   8.736 +static struct hw_interrupt_type ioapic_edge_type;
   8.737 +
   8.738 +#define IOAPIC_AUTO	-1
   8.739 +#define IOAPIC_EDGE	0
   8.740 +#define IOAPIC_LEVEL	1
   8.741 +
   8.742 +static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger)
   8.743 +{
   8.744 +	if (use_pci_vector() && !platform_legacy_irq(irq)) {
   8.745 +		if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
   8.746 +				trigger == IOAPIC_LEVEL)
   8.747 +			irq_desc[vector].handler = &ioapic_level_type;
   8.748 +		else
   8.749 +			irq_desc[vector].handler = &ioapic_edge_type;
   8.750 +		set_intr_gate(vector, interrupt[vector]);
   8.751 +	} else	{
   8.752 +		if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
   8.753 +				trigger == IOAPIC_LEVEL)
   8.754 +			irq_desc[irq].handler = &ioapic_level_type;
   8.755 +		else
   8.756 +			irq_desc[irq].handler = &ioapic_edge_type;
   8.757 +		set_intr_gate(vector, interrupt[irq]);
   8.758 +	}
   8.759 +}
   8.760 +#else
   8.761 +#define ioapic_register_intr(_irq,_vector,_trigger) ((void)0)
   8.762 +#endif /* !CONFIG_XEN */
   8.763 +
   8.764 +void __init setup_IO_APIC_irqs(void)
   8.765 +{
   8.766 +	struct IO_APIC_route_entry entry;
   8.767 +	int apic, pin, idx, irq, first_notcon = 1, vector;
   8.768 +	unsigned long flags;
   8.769 +
   8.770 +	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
   8.771 +
   8.772 +	for (apic = 0; apic < nr_ioapics; apic++) {
   8.773 +	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
   8.774 +
   8.775 +		/*
   8.776 +		 * add it to the IO-APIC irq-routing table:
   8.777 +		 */
   8.778 +		memset(&entry,0,sizeof(entry));
   8.779 +
   8.780 +		entry.delivery_mode = INT_DELIVERY_MODE;
   8.781 +		entry.dest_mode = INT_DEST_MODE;
   8.782 +		entry.mask = 0;				/* enable IRQ */
   8.783 +		entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
   8.784 +
   8.785 +		idx = find_irq_entry(apic,pin,mp_INT);
   8.786 +		if (idx == -1) {
   8.787 +			if (first_notcon) {
   8.788 +				apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);
   8.789 +				first_notcon = 0;
   8.790 +			} else
   8.791 +				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
   8.792 +			continue;
   8.793 +		}
   8.794 +
   8.795 +		entry.trigger = irq_trigger(idx);
   8.796 +		entry.polarity = irq_polarity(idx);
   8.797 +
   8.798 +		if (irq_trigger(idx)) {
   8.799 +			entry.trigger = 1;
   8.800 +			entry.mask = 1;
   8.801 +			entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
   8.802 +		}
   8.803 +
   8.804 +		irq = pin_2_irq(idx, apic, pin);
   8.805 +		add_pin_to_irq(irq, apic, pin);
   8.806 +
   8.807 +		if (/* !apic && */ !IO_APIC_IRQ(irq))
   8.808 +			continue;
   8.809 +
   8.810 +		if (IO_APIC_IRQ(irq)) {
   8.811 +			vector = assign_irq_vector(irq);
   8.812 +			entry.vector = vector;
   8.813 +
   8.814 +			ioapic_register_intr(irq, vector, IOAPIC_AUTO);
   8.815 +			if (!apic && (irq < 16))
   8.816 +				disable_8259A_irq(irq);
   8.817 +		}
   8.818 +		spin_lock_irqsave(&ioapic_lock, flags);
   8.819 +		io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
   8.820 +		io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
   8.821 +		spin_unlock_irqrestore(&ioapic_lock, flags);
   8.822 +	}
   8.823 +	}
   8.824 +
   8.825 +	if (!first_notcon)
   8.826 +		apic_printk(APIC_VERBOSE," not connected.\n");
   8.827 +}
   8.828 +
   8.829 +#ifndef CONFIG_XEN
   8.830 +/*
   8.831 + * Set up the 8259A-master output pin as broadcast to all
   8.832 + * CPUs.
   8.833 + */
   8.834 +void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
   8.835 +{
   8.836 +	struct IO_APIC_route_entry entry;
   8.837 +	unsigned long flags;
   8.838 +
   8.839 +	memset(&entry,0,sizeof(entry));
   8.840 +
   8.841 +	disable_8259A_irq(0);
   8.842 +
   8.843 +	/* mask LVT0 */
   8.844 +	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
   8.845 +
   8.846 +	/*
   8.847 +	 * We use logical delivery to get the timer IRQ
   8.848 +	 * to the first CPU.
   8.849 +	 */
   8.850 +	entry.dest_mode = INT_DEST_MODE;
   8.851 +	entry.mask = 0;					/* unmask IRQ now */
   8.852 +	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
   8.853 +	entry.delivery_mode = INT_DELIVERY_MODE;
   8.854 +	entry.polarity = 0;
   8.855 +	entry.trigger = 0;
   8.856 +	entry.vector = vector;
   8.857 +
   8.858 +	/*
   8.859 +	 * The timer IRQ doesn't have to know that behind the
   8.860 +	 * scene we have a 8259A-master in AEOI mode ...
   8.861 +	 */
   8.862 +	irq_desc[0].handler = &ioapic_edge_type;
   8.863 +
   8.864 +	/*
   8.865 +	 * Add it to the IO-APIC irq-routing table:
   8.866 +	 */
   8.867 +	spin_lock_irqsave(&ioapic_lock, flags);
   8.868 +	io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
   8.869 +	io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
   8.870 +	spin_unlock_irqrestore(&ioapic_lock, flags);
   8.871 +
   8.872 +	enable_8259A_irq(0);
   8.873 +}
   8.874 +
   8.875 +void __init UNEXPECTED_IO_APIC(void)
   8.876 +{
   8.877 +}
   8.878 +
   8.879 +void __apicdebuginit print_IO_APIC(void)
   8.880 +{
   8.881 +	int apic, i;
   8.882 +	union IO_APIC_reg_00 reg_00;
   8.883 +	union IO_APIC_reg_01 reg_01;
   8.884 +	union IO_APIC_reg_02 reg_02;
   8.885 +	unsigned long flags;
   8.886 +
   8.887 +	if (apic_verbosity == APIC_QUIET)
   8.888 +		return;
   8.889 +
   8.890 +	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
   8.891 +	for (i = 0; i < nr_ioapics; i++)
   8.892 +		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
   8.893 +		       mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);
   8.894 +
   8.895 +	/*
   8.896 +	 * We are a bit conservative about what we expect.  We have to
   8.897 +	 * know about every hardware change ASAP.
   8.898 +	 */
   8.899 +	printk(KERN_INFO "testing the IO APIC.......................\n");
   8.900 +
   8.901 +	for (apic = 0; apic < nr_ioapics; apic++) {
   8.902 +
   8.903 +	spin_lock_irqsave(&ioapic_lock, flags);
   8.904 +	reg_00.raw = io_apic_read(apic, 0);
   8.905 +	reg_01.raw = io_apic_read(apic, 1);
   8.906 +	if (reg_01.bits.version >= 0x10)
   8.907 +		reg_02.raw = io_apic_read(apic, 2);
   8.908 +	spin_unlock_irqrestore(&ioapic_lock, flags);
   8.909 +
   8.910 +	printk("\n");
   8.911 +	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
   8.912 +	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
   8.913 +	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
   8.914 +	if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)
   8.915 +		UNEXPECTED_IO_APIC();
   8.916 +
   8.917 +	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
   8.918 +	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
   8.919 +	if (	(reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */
   8.920 +		(reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */
   8.921 +		(reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */
   8.922 +		(reg_01.bits.entries != 0x1f) && /* dual Xeon boards */
   8.923 +		(reg_01.bits.entries != 0x22) && /* bigger Xeon boards */
   8.924 +		(reg_01.bits.entries != 0x2E) &&
   8.925 +		(reg_01.bits.entries != 0x3F) &&
   8.926 +		(reg_01.bits.entries != 0x03) 
   8.927 +	)
   8.928 +		UNEXPECTED_IO_APIC();
   8.929 +
   8.930 +	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
   8.931 +	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
   8.932 +	if (	(reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */
   8.933 +		(reg_01.bits.version != 0x02) && /* 82801BA IO-APICs (ICH2) */
   8.934 +		(reg_01.bits.version != 0x10) && /* oldest IO-APICs */
   8.935 +		(reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */
   8.936 +		(reg_01.bits.version != 0x13) && /* Xeon IO-APICs */
   8.937 +		(reg_01.bits.version != 0x20)    /* Intel P64H (82806 AA) */
   8.938 +	)
   8.939 +		UNEXPECTED_IO_APIC();
   8.940 +	if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2)
   8.941 +		UNEXPECTED_IO_APIC();
   8.942 +
   8.943 +	if (reg_01.bits.version >= 0x10) {
   8.944 +		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
   8.945 +		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
   8.946 +		if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2)
   8.947 +			UNEXPECTED_IO_APIC();
   8.948 +	}
   8.949 +
   8.950 +	printk(KERN_DEBUG ".... IRQ redirection table:\n");
   8.951 +
   8.952 +	printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
   8.953 +			  " Stat Dest Deli Vect:   \n");
   8.954 +
   8.955 +	for (i = 0; i <= reg_01.bits.entries; i++) {
   8.956 +		struct IO_APIC_route_entry entry;
   8.957 +
   8.958 +		spin_lock_irqsave(&ioapic_lock, flags);
   8.959 +		*(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
   8.960 +		*(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
   8.961 +		spin_unlock_irqrestore(&ioapic_lock, flags);
   8.962 +
   8.963 +		printk(KERN_DEBUG " %02x %03X %02X  ",
   8.964 +			i,
   8.965 +			entry.dest.logical.logical_dest,
   8.966 +			entry.dest.physical.physical_dest
   8.967 +		);
   8.968 +
   8.969 +		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
   8.970 +			entry.mask,
   8.971 +			entry.trigger,
   8.972 +			entry.irr,
   8.973 +			entry.polarity,
   8.974 +			entry.delivery_status,
   8.975 +			entry.dest_mode,
   8.976 +			entry.delivery_mode,
   8.977 +			entry.vector
   8.978 +		);
   8.979 +	}
   8.980 +	}
   8.981 +	if (use_pci_vector())
   8.982 +		printk(KERN_INFO "Using vector-based indexing\n");
   8.983 +	printk(KERN_DEBUG "IRQ to pin mappings:\n");
   8.984 +	for (i = 0; i < NR_IRQS; i++) {
   8.985 +		struct irq_pin_list *entry = irq_2_pin + i;
   8.986 +		if (entry->pin < 0)
   8.987 +			continue;
   8.988 + 		if (use_pci_vector() && !platform_legacy_irq(i))
   8.989 +			printk(KERN_DEBUG "IRQ%d ", IO_APIC_VECTOR(i));
   8.990 +		else
   8.991 +			printk(KERN_DEBUG "IRQ%d ", i);
   8.992 +		for (;;) {
   8.993 +			printk("-> %d:%d", entry->apic, entry->pin);
   8.994 +			if (!entry->next)
   8.995 +				break;
   8.996 +			entry = irq_2_pin + entry->next;
   8.997 +		}
   8.998 +		printk("\n");
   8.999 +	}
  8.1000 +
  8.1001 +	printk(KERN_INFO ".................................... done.\n");
  8.1002 +
  8.1003 +	return;
  8.1004 +}
  8.1005 +
  8.1006 +static __apicdebuginit void print_APIC_bitfield (int base)
  8.1007 +{
  8.1008 +	unsigned int v;
  8.1009 +	int i, j;
  8.1010 +
  8.1011 +	if (apic_verbosity == APIC_QUIET)
  8.1012 +		return;
  8.1013 +
  8.1014 +	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
  8.1015 +	for (i = 0; i < 8; i++) {
  8.1016 +		v = apic_read(base + i*0x10);
  8.1017 +		for (j = 0; j < 32; j++) {
  8.1018 +			if (v & (1<<j))
  8.1019 +				printk("1");
  8.1020 +			else
  8.1021 +				printk("0");
  8.1022 +		}
  8.1023 +		printk("\n");
  8.1024 +	}
  8.1025 +}
  8.1026 +
  8.1027 +void __apicdebuginit print_local_APIC(void * dummy)
  8.1028 +{
  8.1029 +	unsigned int v, ver, maxlvt;
  8.1030 +
  8.1031 +	if (apic_verbosity == APIC_QUIET)
  8.1032 +		return;
  8.1033 +
  8.1034 +	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
  8.1035 +		smp_processor_id(), hard_smp_processor_id());
  8.1036 +	v = apic_read(APIC_ID);
  8.1037 +	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(v));
  8.1038 +	v = apic_read(APIC_LVR);
  8.1039 +	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
  8.1040 +	ver = GET_APIC_VERSION(v);
  8.1041 +	maxlvt = get_maxlvt();
  8.1042 +
  8.1043 +	v = apic_read(APIC_TASKPRI);
  8.1044 +	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
  8.1045 +
  8.1046 +	if (APIC_INTEGRATED(ver)) {			/* !82489DX */
  8.1047 +		v = apic_read(APIC_ARBPRI);
  8.1048 +		printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
  8.1049 +			v & APIC_ARBPRI_MASK);
  8.1050 +		v = apic_read(APIC_PROCPRI);
  8.1051 +		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
  8.1052 +	}
  8.1053 +
  8.1054 +	v = apic_read(APIC_EOI);
  8.1055 +	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
  8.1056 +	v = apic_read(APIC_RRR);
  8.1057 +	printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
  8.1058 +	v = apic_read(APIC_LDR);
  8.1059 +	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
  8.1060 +	v = apic_read(APIC_DFR);
  8.1061 +	printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
  8.1062 +	v = apic_read(APIC_SPIV);
  8.1063 +	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
  8.1064 +
  8.1065 +	printk(KERN_DEBUG "... APIC ISR field:\n");
  8.1066 +	print_APIC_bitfield(APIC_ISR);
  8.1067 +	printk(KERN_DEBUG "... APIC TMR field:\n");
  8.1068 +	print_APIC_bitfield(APIC_TMR);
  8.1069 +	printk(KERN_DEBUG "... APIC IRR field:\n");
  8.1070 +	print_APIC_bitfield(APIC_IRR);
  8.1071 +
  8.1072 +	if (APIC_INTEGRATED(ver)) {		/* !82489DX */
  8.1073 +		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
  8.1074 +			apic_write(APIC_ESR, 0);
  8.1075 +		v = apic_read(APIC_ESR);
  8.1076 +		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
  8.1077 +	}
  8.1078 +
  8.1079 +	v = apic_read(APIC_ICR);
  8.1080 +	printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
  8.1081 +	v = apic_read(APIC_ICR2);
  8.1082 +	printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);
  8.1083 +
  8.1084 +	v = apic_read(APIC_LVTT);
  8.1085 +	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
  8.1086 +
  8.1087 +	if (maxlvt > 3) {                       /* PC is LVT#4. */
  8.1088 +		v = apic_read(APIC_LVTPC);
  8.1089 +		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);
  8.1090 +	}
  8.1091 +	v = apic_read(APIC_LVT0);
  8.1092 +	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);
  8.1093 +	v = apic_read(APIC_LVT1);
  8.1094 +	printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);
  8.1095 +
  8.1096 +	if (maxlvt > 2) {			/* ERR is LVT#3. */
  8.1097 +		v = apic_read(APIC_LVTERR);
  8.1098 +		printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);
  8.1099 +	}
  8.1100 +
  8.1101 +	v = apic_read(APIC_TMICT);
  8.1102 +	printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);
  8.1103 +	v = apic_read(APIC_TMCCT);
  8.1104 +	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
  8.1105 +	v = apic_read(APIC_TDCR);
  8.1106 +	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
  8.1107 +	printk("\n");
  8.1108 +}
  8.1109 +
  8.1110 +void print_all_local_APICs (void)
  8.1111 +{
  8.1112 +	on_each_cpu(print_local_APIC, NULL, 1, 1);
  8.1113 +}
  8.1114 +
  8.1115 +void __apicdebuginit print_PIC(void)
  8.1116 +{
  8.1117 +	extern spinlock_t i8259A_lock;
  8.1118 +	unsigned int v;
  8.1119 +	unsigned long flags;
  8.1120 +
  8.1121 +	if (apic_verbosity == APIC_QUIET)
  8.1122 +		return;
  8.1123 +
  8.1124 +	printk(KERN_DEBUG "\nprinting PIC contents\n");
  8.1125 +
  8.1126 +	spin_lock_irqsave(&i8259A_lock, flags);
  8.1127 +
  8.1128 +	v = inb(0xa1) << 8 | inb(0x21);
  8.1129 +	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
  8.1130 +
  8.1131 +	v = inb(0xa0) << 8 | inb(0x20);
  8.1132 +	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
  8.1133 +
  8.1134 +	outb(0x0b,0xa0);
  8.1135 +	outb(0x0b,0x20);
  8.1136 +	v = inb(0xa0) << 8 | inb(0x20);
  8.1137 +	outb(0x0a,0xa0);
  8.1138 +	outb(0x0a,0x20);
  8.1139 +
  8.1140 +	spin_unlock_irqrestore(&i8259A_lock, flags);
  8.1141 +
  8.1142 +	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
  8.1143 +
  8.1144 +	v = inb(0x4d1) << 8 | inb(0x4d0);
  8.1145 +	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
  8.1146 +}
  8.1147 +#else
  8.1148 +void __init print_IO_APIC(void) { }
  8.1149 +#endif /* !CONFIG_XEN */
  8.1150 +
  8.1151 +static void __init enable_IO_APIC(void)
  8.1152 +{
  8.1153 +	union IO_APIC_reg_01 reg_01;
  8.1154 +	int i;
  8.1155 +	unsigned long flags;
  8.1156 +
  8.1157 +	for (i = 0; i < PIN_MAP_SIZE; i++) {
  8.1158 +		irq_2_pin[i].pin = -1;
  8.1159 +		irq_2_pin[i].next = 0;
  8.1160 +	}
  8.1161 +	if (!pirqs_enabled)
  8.1162 +		for (i = 0; i < MAX_PIRQS; i++)
  8.1163 +			pirq_entries[i] = -1;
  8.1164 +
  8.1165 +	/*
  8.1166 +	 * The number of IO-APIC IRQ registers (== #pins):
  8.1167 +	 */
  8.1168 +	for (i = 0; i < nr_ioapics; i++) {
  8.1169 +		spin_lock_irqsave(&ioapic_lock, flags);
  8.1170 +		reg_01.raw = io_apic_read(i, 1);
  8.1171 +		spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1172 +		nr_ioapic_registers[i] = reg_01.bits.entries+1;
  8.1173 +	}
  8.1174 +
  8.1175 +	/*
  8.1176 +	 * Do not trust the IO-APIC being empty at bootup
  8.1177 +	 */
  8.1178 +	clear_IO_APIC();
  8.1179 +}
  8.1180 +
  8.1181 +/*
  8.1182 + * Not an __init, needed by the reboot code
  8.1183 + */
  8.1184 +void disable_IO_APIC(void)
  8.1185 +{
  8.1186 +	/*
  8.1187 +	 * Clear the IO-APIC before rebooting:
  8.1188 +	 */
  8.1189 +	clear_IO_APIC();
  8.1190 +#ifndef CONFIG_XEN
  8.1191 +	disconnect_bsp_APIC();
  8.1192 +#endif
  8.1193 +}
  8.1194 +
  8.1195 +/*
  8.1196 + * function to set the IO-APIC physical IDs based on the
  8.1197 + * values stored in the MPC table.
  8.1198 + *
  8.1199 + * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
  8.1200 + */
  8.1201 +#ifndef CONFIG_XEN
  8.1202 +static void __init setup_ioapic_ids_from_mpc (void)
  8.1203 +{
  8.1204 +	union IO_APIC_reg_00 reg_00;
  8.1205 +	int apic;
  8.1206 +	int i;
  8.1207 +	unsigned char old_id;
  8.1208 +	unsigned long flags;
  8.1209 +
  8.1210 +	/*
  8.1211 +	 * Set the IOAPIC ID to the value stored in the MPC table.
  8.1212 +	 */
  8.1213 +	for (apic = 0; apic < nr_ioapics; apic++) {
  8.1214 +
  8.1215 +		/* Read the register 0 value */
  8.1216 +		spin_lock_irqsave(&ioapic_lock, flags);
  8.1217 +		reg_00.raw = io_apic_read(apic, 0);
  8.1218 +		spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1219 +		
  8.1220 +		old_id = mp_ioapics[apic].mpc_apicid;
  8.1221 +
  8.1222 +
  8.1223 +		printk(KERN_INFO "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid);
  8.1224 +
  8.1225 +
  8.1226 +		/*
  8.1227 +		 * We need to adjust the IRQ routing table
  8.1228 +		 * if the ID changed.
  8.1229 +		 */
  8.1230 +		if (old_id != mp_ioapics[apic].mpc_apicid)
  8.1231 +			for (i = 0; i < mp_irq_entries; i++)
  8.1232 +				if (mp_irqs[i].mpc_dstapic == old_id)
  8.1233 +					mp_irqs[i].mpc_dstapic
  8.1234 +						= mp_ioapics[apic].mpc_apicid;
  8.1235 +
  8.1236 +		/*
  8.1237 +		 * Read the right value from the MPC table and
  8.1238 +		 * write it into the ID register.
  8.1239 +	 	 */
  8.1240 +		apic_printk(APIC_VERBOSE,KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
  8.1241 +				mp_ioapics[apic].mpc_apicid);
  8.1242 +
  8.1243 +		reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
  8.1244 +		spin_lock_irqsave(&ioapic_lock, flags);
  8.1245 +		io_apic_write(apic, 0, reg_00.raw);
  8.1246 +		spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1247 +
  8.1248 +		/*
  8.1249 +		 * Sanity check
  8.1250 +		 */
  8.1251 +		spin_lock_irqsave(&ioapic_lock, flags);
  8.1252 +		reg_00.raw = io_apic_read(apic, 0);
  8.1253 +		spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1254 +		if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
  8.1255 +			printk("could not set ID!\n");
  8.1256 +		else
  8.1257 +			apic_printk(APIC_VERBOSE," ok.\n");
  8.1258 +	}
  8.1259 +}
  8.1260 +#else
  8.1261 +static void __init setup_ioapic_ids_from_mpc(void) { }
  8.1262 +#endif
  8.1263 +
  8.1264 +/*
  8.1265 + * There is a nasty bug in some older SMP boards, their mptable lies
  8.1266 + * about the timer IRQ. We do the following to work around the situation:
  8.1267 + *
  8.1268 + *	- timer IRQ defaults to IO-APIC IRQ
  8.1269 + *	- if this function detects that timer IRQs are defunct, then we fall
  8.1270 + *	  back to ISA timer IRQs
  8.1271 + */
  8.1272 +#ifndef CONFIG_XEN
  8.1273 +static int __init timer_irq_works(void)
  8.1274 +{
  8.1275 +	unsigned long t1 = jiffies;
  8.1276 +
  8.1277 +	local_irq_enable();
  8.1278 +	/* Let ten ticks pass... */
  8.1279 +	mdelay((10 * 1000) / HZ);
  8.1280 +
  8.1281 +	/*
  8.1282 +	 * Expect a few ticks at least, to be sure some possible
  8.1283 +	 * glue logic does not lock up after one or two first
  8.1284 +	 * ticks in a non-ExtINT mode.  Also the local APIC
  8.1285 +	 * might have cached one ExtINT interrupt.  Finally, at
  8.1286 +	 * least one tick may be lost due to delays.
  8.1287 +	 */
  8.1288 +
  8.1289 +	/* jiffies wrap? */
  8.1290 +	if (jiffies - t1 > 4)
  8.1291 +		return 1;
  8.1292 +	return 0;
  8.1293 +}
  8.1294 +
  8.1295 +/*
  8.1296 + * In the SMP+IOAPIC case it might happen that there are an unspecified
  8.1297 + * number of pending IRQ events unhandled. These cases are very rare,
  8.1298 + * so we 'resend' these IRQs via IPIs, to the same CPU. It's much
  8.1299 + * better to do it this way as thus we do not have to be aware of
  8.1300 + * 'pending' interrupts in the IRQ path, except at this point.
  8.1301 + */
  8.1302 +/*
  8.1303 + * Edge triggered needs to resend any interrupt
  8.1304 + * that was delayed but this is now handled in the device
  8.1305 + * independent code.
  8.1306 + */
  8.1307 +
  8.1308 +/*
  8.1309 + * Starting up a edge-triggered IO-APIC interrupt is
  8.1310 + * nasty - we need to make sure that we get the edge.
  8.1311 + * If it is already asserted for some reason, we need
  8.1312 + * return 1 to indicate that is was pending.
  8.1313 + *
  8.1314 + * This is not complete - we should be able to fake
  8.1315 + * an edge even if it isn't on the 8259A...
  8.1316 + */
  8.1317 +
  8.1318 +static unsigned int startup_edge_ioapic_irq(unsigned int irq)
  8.1319 +{
  8.1320 +	int was_pending = 0;
  8.1321 +	unsigned long flags;
  8.1322 +
  8.1323 +	spin_lock_irqsave(&ioapic_lock, flags);
  8.1324 +	if (irq < 16) {
  8.1325 +		disable_8259A_irq(irq);
  8.1326 +		if (i8259A_irq_pending(irq))
  8.1327 +			was_pending = 1;
  8.1328 +	}
  8.1329 +	__unmask_IO_APIC_irq(irq);
  8.1330 +	spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1331 +
  8.1332 +	return was_pending;
  8.1333 +}
  8.1334 +
  8.1335 +/*
  8.1336 + * Once we have recorded IRQ_PENDING already, we can mask the
  8.1337 + * interrupt for real. This prevents IRQ storms from unhandled
  8.1338 + * devices.
  8.1339 + */
  8.1340 +static void ack_edge_ioapic_irq(unsigned int irq)
  8.1341 +{
  8.1342 +	if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
  8.1343 +					== (IRQ_PENDING | IRQ_DISABLED))
  8.1344 +		mask_IO_APIC_irq(irq);
  8.1345 +	ack_APIC_irq();
  8.1346 +}
  8.1347 +
  8.1348 +/*
  8.1349 + * Level triggered interrupts can just be masked,
  8.1350 + * and shutting down and starting up the interrupt
  8.1351 + * is the same as enabling and disabling them -- except
  8.1352 + * with a startup need to return a "was pending" value.
  8.1353 + *
  8.1354 + * Level triggered interrupts are special because we
  8.1355 + * do not touch any IO-APIC register while handling
  8.1356 + * them. We ack the APIC in the end-IRQ handler, not
  8.1357 + * in the start-IRQ-handler. Protection against reentrance
  8.1358 + * from the same interrupt is still provided, both by the
  8.1359 + * generic IRQ layer and by the fact that an unacked local
  8.1360 + * APIC does not accept IRQs.
  8.1361 + */
  8.1362 +static unsigned int startup_level_ioapic_irq (unsigned int irq)
  8.1363 +{
  8.1364 +	unmask_IO_APIC_irq(irq);
  8.1365 +
  8.1366 +	return 0; /* don't check for pending */
  8.1367 +}
  8.1368 +
  8.1369 +static void end_level_ioapic_irq (unsigned int irq)
  8.1370 +{
  8.1371 +	ack_APIC_irq();
  8.1372 +}
  8.1373 +
  8.1374 +static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
  8.1375 +{
  8.1376 +	unsigned long flags;
  8.1377 +	unsigned int dest;
  8.1378 +
  8.1379 +	dest = cpu_mask_to_apicid(mask);
  8.1380 +
  8.1381 +	/*
  8.1382 +	 * Only the high 8 bits are valid.
  8.1383 +	 */
  8.1384 +	dest = SET_APIC_LOGICAL_ID(dest);
  8.1385 +
  8.1386 +	spin_lock_irqsave(&ioapic_lock, flags);
  8.1387 +	__DO_ACTION(1, = dest, )
  8.1388 +	spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1389 +}
  8.1390 +
  8.1391 +#ifdef CONFIG_PCI_MSI
  8.1392 +static unsigned int startup_edge_ioapic_vector(unsigned int vector)
  8.1393 +{
  8.1394 +	int irq = vector_to_irq(vector);
  8.1395 +
  8.1396 +	return startup_edge_ioapic_irq(irq);
  8.1397 +}
  8.1398 +
  8.1399 +static void ack_edge_ioapic_vector(unsigned int vector)
  8.1400 +{
  8.1401 +	int irq = vector_to_irq(vector);
  8.1402 +
  8.1403 +	ack_edge_ioapic_irq(irq);
  8.1404 +}
  8.1405 +
  8.1406 +static unsigned int startup_level_ioapic_vector (unsigned int vector)
  8.1407 +{
  8.1408 +	int irq = vector_to_irq(vector);
  8.1409 +
  8.1410 +	return startup_level_ioapic_irq (irq);
  8.1411 +}
  8.1412 +
  8.1413 +static void end_level_ioapic_vector (unsigned int vector)
  8.1414 +{
  8.1415 +	int irq = vector_to_irq(vector);
  8.1416 +
  8.1417 +	end_level_ioapic_irq(irq);
  8.1418 +}
  8.1419 +
  8.1420 +static void mask_IO_APIC_vector (unsigned int vector)
  8.1421 +{
  8.1422 +	int irq = vector_to_irq(vector);
  8.1423 +
  8.1424 +	mask_IO_APIC_irq(irq);
  8.1425 +}
  8.1426 +
  8.1427 +static void unmask_IO_APIC_vector (unsigned int vector)
  8.1428 +{
  8.1429 +	int irq = vector_to_irq(vector);
  8.1430 +
  8.1431 +	unmask_IO_APIC_irq(irq);
  8.1432 +}
  8.1433 +
  8.1434 +static void set_ioapic_affinity_vector (unsigned int vector,
  8.1435 +					cpumask_t cpu_mask)
  8.1436 +{
  8.1437 +	int irq = vector_to_irq(vector);
  8.1438 +
  8.1439 +	set_ioapic_affinity_irq(irq, cpu_mask);
  8.1440 +}
  8.1441 +#endif
  8.1442 +
  8.1443 +/*
  8.1444 + * Level and edge triggered IO-APIC interrupts need different handling,
  8.1445 + * so we use two separate IRQ descriptors. Edge triggered IRQs can be
  8.1446 + * handled with the level-triggered descriptor, but that one has slightly
  8.1447 + * more overhead. Level-triggered interrupts cannot be handled with the
  8.1448 + * edge-triggered handler, without risking IRQ storms and other ugly
  8.1449 + * races.
  8.1450 + */
  8.1451 +
  8.1452 +static struct hw_interrupt_type ioapic_edge_type = {
  8.1453 +	.typename = "IO-APIC-edge",
  8.1454 +	.startup 	= startup_edge_ioapic,
  8.1455 +	.shutdown 	= shutdown_edge_ioapic,
  8.1456 +	.enable 	= enable_edge_ioapic,
  8.1457 +	.disable 	= disable_edge_ioapic,
  8.1458 +	.ack 		= ack_edge_ioapic,
  8.1459 +	.end 		= end_edge_ioapic,
  8.1460 +	.set_affinity = set_ioapic_affinity,
  8.1461 +};
  8.1462 +
  8.1463 +static struct hw_interrupt_type ioapic_level_type = {
  8.1464 +	.typename = "IO-APIC-level",
  8.1465 +	.startup 	= startup_level_ioapic,
  8.1466 +	.shutdown 	= shutdown_level_ioapic,
  8.1467 +	.enable 	= enable_level_ioapic,
  8.1468 +	.disable 	= disable_level_ioapic,
  8.1469 +	.ack 		= mask_and_ack_level_ioapic,
  8.1470 +	.end 		= end_level_ioapic,
  8.1471 +	.set_affinity = set_ioapic_affinity,
  8.1472 +};
  8.1473 +#endif /* !CONFIG_XEN */
  8.1474 +
  8.1475 +static inline void init_IO_APIC_traps(void)
  8.1476 +{
  8.1477 +	int irq;
  8.1478 +
  8.1479 +	/*
  8.1480 +	 * NOTE! The local APIC isn't very good at handling
  8.1481 +	 * multiple interrupts at the same interrupt level.
  8.1482 +	 * As the interrupt level is determined by taking the
  8.1483 +	 * vector number and shifting that right by 4, we
  8.1484 +	 * want to spread these out a bit so that they don't
  8.1485 +	 * all fall in the same interrupt level.
  8.1486 +	 *
  8.1487 +	 * Also, we've got to be careful not to trash gate
  8.1488 +	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
  8.1489 +	 */
  8.1490 +	for (irq = 0; irq < NR_IRQS ; irq++) {
  8.1491 +		int tmp = irq;
  8.1492 +		if (use_pci_vector()) {
  8.1493 +			if (!platform_legacy_irq(tmp))
  8.1494 +				if ((tmp = vector_to_irq(tmp)) == -1)
  8.1495 +					continue;
  8.1496 +		}
  8.1497 +		if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) {
  8.1498 +			/*
  8.1499 +			 * Hmm.. We don't have an entry for this,
  8.1500 +			 * so default to an old-fashioned 8259
  8.1501 +			 * interrupt if we can..
  8.1502 +			 */
  8.1503 +			if (irq < 16)
  8.1504 +				make_8259A_irq(irq);
  8.1505 +#ifndef CONFIG_XEN
  8.1506 +			else
  8.1507 +				/* Strange. Oh, well.. */
  8.1508 +				irq_desc[irq].handler = &no_irq_type;
  8.1509 +#endif
  8.1510 +		}
  8.1511 +	}
  8.1512 +}
  8.1513 +
  8.1514 +#ifndef CONFIG_XEN
  8.1515 +static void enable_lapic_irq (unsigned int irq)
  8.1516 +{
  8.1517 +	unsigned long v;
  8.1518 +
  8.1519 +	v = apic_read(APIC_LVT0);
  8.1520 +	apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED);
  8.1521 +}
  8.1522 +
  8.1523 +static void disable_lapic_irq (unsigned int irq)
  8.1524 +{
  8.1525 +	unsigned long v;
  8.1526 +
  8.1527 +	v = apic_read(APIC_LVT0);
  8.1528 +	apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
  8.1529 +}
  8.1530 +
  8.1531 +static void ack_lapic_irq (unsigned int irq)
  8.1532 +{
  8.1533 +	ack_APIC_irq();
  8.1534 +}
  8.1535 +
  8.1536 +static void end_lapic_irq (unsigned int i) { /* nothing */ }
  8.1537 +
  8.1538 +static struct hw_interrupt_type lapic_irq_type = {
  8.1539 +	.typename = "local-APIC-edge",
  8.1540 +	.startup = NULL, /* startup_irq() not used for IRQ0 */
  8.1541 +	.shutdown = NULL, /* shutdown_irq() not used for IRQ0 */
  8.1542 +	.enable = enable_lapic_irq,
  8.1543 +	.disable = disable_lapic_irq,
  8.1544 +	.ack = ack_lapic_irq,
  8.1545 +	.end = end_lapic_irq,
  8.1546 +};
  8.1547 +
  8.1548 +static void setup_nmi (void)
  8.1549 +{
  8.1550 +	/*
  8.1551 + 	 * Dirty trick to enable the NMI watchdog ...
  8.1552 +	 * We put the 8259A master into AEOI mode and
  8.1553 +	 * unmask on all local APICs LVT0 as NMI.
  8.1554 +	 *
  8.1555 +	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
  8.1556 +	 * is from Maciej W. Rozycki - so we do not have to EOI from
  8.1557 +	 * the NMI handler or the timer interrupt.
  8.1558 +	 */ 
  8.1559 +	printk(KERN_INFO "activating NMI Watchdog ...");
  8.1560 +
  8.1561 +	enable_NMI_through_LVT0(NULL);
  8.1562 +
  8.1563 +	printk(" done.\n");
  8.1564 +}
  8.1565 +
  8.1566 +/*
  8.1567 + * This looks a bit hackish but it's about the only one way of sending
  8.1568 + * a few INTA cycles to 8259As and any associated glue logic.  ICR does
  8.1569 + * not support the ExtINT mode, unfortunately.  We need to send these
  8.1570 + * cycles as some i82489DX-based boards have glue logic that keeps the
  8.1571 + * 8259A interrupt line asserted until INTA.  --macro
  8.1572 + */
  8.1573 +static inline void unlock_ExtINT_logic(void)
  8.1574 +{
  8.1575 +	int pin, i;
  8.1576 +	struct IO_APIC_route_entry entry0, entry1;
  8.1577 +	unsigned char save_control, save_freq_select;
  8.1578 +	unsigned long flags;
  8.1579 +
  8.1580 +	pin = find_isa_irq_pin(8, mp_INT);
  8.1581 +	if (pin == -1)
  8.1582 +		return;
  8.1583 +
  8.1584 +	spin_lock_irqsave(&ioapic_lock, flags);
  8.1585 +	*(((int *)&entry0) + 1) = io_apic_read(0, 0x11 + 2 * pin);
  8.1586 +	*(((int *)&entry0) + 0) = io_apic_read(0, 0x10 + 2 * pin);
  8.1587 +	spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1588 +	clear_IO_APIC_pin(0, pin);
  8.1589 +
  8.1590 +	memset(&entry1, 0, sizeof(entry1));
  8.1591 +
  8.1592 +	entry1.dest_mode = 0;			/* physical delivery */
  8.1593 +	entry1.mask = 0;			/* unmask IRQ now */
  8.1594 +	entry1.dest.physical.physical_dest = hard_smp_processor_id();
  8.1595 +	entry1.delivery_mode = dest_ExtINT;
  8.1596 +	entry1.polarity = entry0.polarity;
  8.1597 +	entry1.trigger = 0;
  8.1598 +	entry1.vector = 0;
  8.1599 +
  8.1600 +	spin_lock_irqsave(&ioapic_lock, flags);
  8.1601 +	io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
  8.1602 +	io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
  8.1603 +	spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1604 +
  8.1605 +	save_control = CMOS_READ(RTC_CONTROL);
  8.1606 +	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
  8.1607 +	CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6,
  8.1608 +		   RTC_FREQ_SELECT);
  8.1609 +	CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL);
  8.1610 +
  8.1611 +	i = 100;
  8.1612 +	while (i-- > 0) {
  8.1613 +		mdelay(10);
  8.1614 +		if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF)
  8.1615 +			i -= 10;
  8.1616 +	}
  8.1617 +
  8.1618 +	CMOS_WRITE(save_control, RTC_CONTROL);
  8.1619 +	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
  8.1620 +	clear_IO_APIC_pin(0, pin);
  8.1621 +
  8.1622 +	spin_lock_irqsave(&ioapic_lock, flags);
  8.1623 +	io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
  8.1624 +	io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
  8.1625 +	spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1626 +}
  8.1627 +
  8.1628 +/*
  8.1629 + * This code may look a bit paranoid, but it's supposed to cooperate with
  8.1630 + * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
  8.1631 + * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
  8.1632 + * fanatically on his truly buggy board.
  8.1633 + */
  8.1634 +static inline void check_timer(void)
  8.1635 +{
  8.1636 +	int pin1, pin2;
  8.1637 +	int vector;
  8.1638 +
  8.1639 +	/*
  8.1640 +	 * get/set the timer IRQ vector:
  8.1641 +	 */
  8.1642 +	disable_8259A_irq(0);
  8.1643 +	vector = assign_irq_vector(0);
  8.1644 +	set_intr_gate(vector, interrupt[0]);
  8.1645 +
  8.1646 +	/*
  8.1647 +	 * Subtle, code in do_timer_interrupt() expects an AEOI
  8.1648 +	 * mode for the 8259A whenever interrupts are routed
  8.1649 +	 * through I/O APICs.  Also IRQ0 has to be enabled in
  8.1650 +	 * the 8259A which implies the virtual wire has to be
  8.1651 +	 * disabled in the local APIC.
  8.1652 +	 */
  8.1653 +	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
  8.1654 +	init_8259A(1);
  8.1655 +	enable_8259A_irq(0);
  8.1656 +
  8.1657 +	pin1 = find_isa_irq_pin(0, mp_INT);
  8.1658 +	pin2 = find_isa_irq_pin(0, mp_ExtINT);
  8.1659 +
  8.1660 +	apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
  8.1661 +
  8.1662 +	if (pin1 != -1) {
  8.1663 +		/*
  8.1664 +		 * Ok, does IRQ0 through the IOAPIC work?
  8.1665 +		 */
  8.1666 +		unmask_IO_APIC_irq(0);
  8.1667 +		if (timer_irq_works()) {
  8.1668 +			nmi_watchdog_default();
  8.1669 +			if (nmi_watchdog == NMI_IO_APIC) {
  8.1670 +				disable_8259A_irq(0);
  8.1671 +				setup_nmi();
  8.1672 +				enable_8259A_irq(0);
  8.1673 +				check_nmi_watchdog();
  8.1674 +			}
  8.1675 +			return;
  8.1676 +		}
  8.1677 +		clear_IO_APIC_pin(0, pin1);
  8.1678 +		apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
  8.1679 +	}
  8.1680 +
  8.1681 +	apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
  8.1682 +	if (pin2 != -1) {
  8.1683 +		apic_printk(APIC_VERBOSE,"\n..... (found pin %d) ...", pin2);
  8.1684 +		/*
  8.1685 +		 * legacy devices should be connected to IO APIC #0
  8.1686 +		 */
  8.1687 +		setup_ExtINT_IRQ0_pin(pin2, vector);
  8.1688 +		if (timer_irq_works()) {
  8.1689 +			printk("works.\n");
  8.1690 +			nmi_watchdog_default();
  8.1691 +			if (nmi_watchdog == NMI_IO_APIC) {
  8.1692 +				setup_nmi();
  8.1693 +				check_nmi_watchdog();
  8.1694 +			}
  8.1695 +			return;
  8.1696 +		}
  8.1697 +		/*
  8.1698 +		 * Cleanup, just in case ...
  8.1699 +		 */
  8.1700 +		clear_IO_APIC_pin(0, pin2);
  8.1701 +	}
  8.1702 +	printk(" failed.\n");
  8.1703 +
  8.1704 +	if (nmi_watchdog) {
  8.1705 +		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
  8.1706 +		nmi_watchdog = 0;
  8.1707 +	}
  8.1708 +
  8.1709 +	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
  8.1710 +
  8.1711 +	disable_8259A_irq(0);
  8.1712 +	irq_desc[0].handler = &lapic_irq_type;
  8.1713 +	apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
  8.1714 +	enable_8259A_irq(0);
  8.1715 +
  8.1716 +	if (timer_irq_works()) {
  8.1717 +		apic_printk(APIC_QUIET, " works.\n");
  8.1718 +		return;
  8.1719 +	}
  8.1720 +	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
  8.1721 +	apic_printk(APIC_VERBOSE," failed.\n");
  8.1722 +
  8.1723 +	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
  8.1724 +
  8.1725 +	init_8259A(0);
  8.1726 +	make_8259A_irq(0);
  8.1727 +	apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
  8.1728 +
  8.1729 +	unlock_ExtINT_logic();
  8.1730 +
  8.1731 +	if (timer_irq_works()) {
  8.1732 +		apic_printk(APIC_VERBOSE," works.\n");
  8.1733 +		return;
  8.1734 +	}
  8.1735 +	apic_printk(APIC_VERBOSE," failed :(.\n");
  8.1736 +	panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
  8.1737 +}
  8.1738 +#else
  8.1739 +#define check_timer() ((void)0)
  8.1740 +#endif /* !CONFIG_XEN */
  8.1741 +
  8.1742 +/*
  8.1743 + *
  8.1744 + * IRQ's that are handled by the PIC in the MPS IOAPIC case.
  8.1745 + * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
  8.1746 + *   Linux doesn't really care, as it's not actually used
  8.1747 + *   for any interrupt handling anyway.
  8.1748 + */
  8.1749 +#define PIC_IRQS	(1<<2)
  8.1750 +
  8.1751 +void __init setup_IO_APIC(void)
  8.1752 +{
  8.1753 +	enable_IO_APIC();
  8.1754 +
  8.1755 +	if (acpi_ioapic)
  8.1756 +		io_apic_irqs = ~0;	/* all IRQs go through IOAPIC */
  8.1757 +	else
  8.1758 +		io_apic_irqs = ~PIC_IRQS;
  8.1759 +
  8.1760 +	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
  8.1761 +
  8.1762 +	/*
  8.1763 +	 * Set up the IO-APIC IRQ routing table.
  8.1764 +	 */
  8.1765 +	if (!acpi_ioapic)
  8.1766 +		setup_ioapic_ids_from_mpc();
  8.1767 +#ifndef CONFIG_XEN
  8.1768 +	sync_Arb_IDs();
  8.1769 +#endif /* !CONFIG_XEN */
  8.1770 +	setup_IO_APIC_irqs();
  8.1771 +	init_IO_APIC_traps();
  8.1772 +	check_timer();
  8.1773 +	if (!acpi_ioapic)
  8.1774 +		print_IO_APIC();
  8.1775 +}
  8.1776 +
  8.1777 +struct sysfs_ioapic_data {
  8.1778 +	struct sys_device dev;
  8.1779 +	struct IO_APIC_route_entry entry[0];
  8.1780 +};
  8.1781 +static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
  8.1782 +
  8.1783 +static int ioapic_suspend(struct sys_device *dev, u32 state)
  8.1784 +{
  8.1785 +	struct IO_APIC_route_entry *entry;
  8.1786 +	struct sysfs_ioapic_data *data;
  8.1787 +	unsigned long flags;
  8.1788 +	int i;
  8.1789 +
  8.1790 +	data = container_of(dev, struct sysfs_ioapic_data, dev);
  8.1791 +	entry = data->entry;
  8.1792 +	spin_lock_irqsave(&ioapic_lock, flags);
  8.1793 +	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
  8.1794 +		*(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
  8.1795 +		*(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
  8.1796 +	}
  8.1797 +	spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1798 +
  8.1799 +	return 0;
  8.1800 +}
  8.1801 +
  8.1802 +static int ioapic_resume(struct sys_device *dev)
  8.1803 +{
  8.1804 +	struct IO_APIC_route_entry *entry;
  8.1805 +	struct sysfs_ioapic_data *data;
  8.1806 +	unsigned long flags;
  8.1807 +	union IO_APIC_reg_00 reg_00;
  8.1808 +	int i;
  8.1809 +
  8.1810 +	data = container_of(dev, struct sysfs_ioapic_data, dev);
  8.1811 +	entry = data->entry;
  8.1812 +
  8.1813 +	spin_lock_irqsave(&ioapic_lock, flags);
  8.1814 +	reg_00.raw = io_apic_read(dev->id, 0);
  8.1815 +	if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) {
  8.1816 +		reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
  8.1817 +		io_apic_write(dev->id, 0, reg_00.raw);
  8.1818 +	}
  8.1819 +	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
  8.1820 +		io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
  8.1821 +		io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
  8.1822 +	}
  8.1823 +	spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1824 +
  8.1825 +	return 0;
  8.1826 +}
  8.1827 +
  8.1828 +static struct sysdev_class ioapic_sysdev_class = {
  8.1829 +	set_kset_name("ioapic"),
  8.1830 +	.suspend = ioapic_suspend,
  8.1831 +	.resume = ioapic_resume,
  8.1832 +};
  8.1833 +
  8.1834 +static int __init ioapic_init_sysfs(void)
  8.1835 +{
  8.1836 +	struct sys_device * dev;
  8.1837 +	int i, size, error = 0;
  8.1838 +
  8.1839 +	error = sysdev_class_register(&ioapic_sysdev_class);
  8.1840 +	if (error)
  8.1841 +		return error;
  8.1842 +
  8.1843 +	for (i = 0; i < nr_ioapics; i++ ) {
  8.1844 +		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
  8.1845 +			* sizeof(struct IO_APIC_route_entry);
  8.1846 +		mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
  8.1847 +		if (!mp_ioapic_data[i]) {
  8.1848 +			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
  8.1849 +			continue;
  8.1850 +		}
  8.1851 +		memset(mp_ioapic_data[i], 0, size);
  8.1852 +		dev = &mp_ioapic_data[i]->dev;
  8.1853 +		dev->id = i;
  8.1854 +		dev->cls = &ioapic_sysdev_class;
  8.1855 +		error = sysdev_register(dev);
  8.1856 +		if (error) {
  8.1857 +			kfree(mp_ioapic_data[i]);
  8.1858 +			mp_ioapic_data[i] = NULL;
  8.1859 +			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
  8.1860 +			continue;
  8.1861 +		}
  8.1862 +	}
  8.1863 +
  8.1864 +	return 0;
  8.1865 +}
  8.1866 +
  8.1867 +device_initcall(ioapic_init_sysfs);
  8.1868 +
  8.1869 +/* --------------------------------------------------------------------------
  8.1870 +                          ACPI-based IOAPIC Configuration
  8.1871 +   -------------------------------------------------------------------------- */
  8.1872 +
  8.1873 +#ifdef CONFIG_ACPI_BOOT
  8.1874 +
  8.1875 +#define IO_APIC_MAX_ID		0xFE
  8.1876 +
  8.1877 +int __init io_apic_get_unique_id (int ioapic, int apic_id)
  8.1878 +{
  8.1879 +#ifndef CONFIG_XEN
  8.1880 +	union IO_APIC_reg_00 reg_00;
  8.1881 +	static physid_mask_t apic_id_map;
  8.1882 +	unsigned long flags;
  8.1883 +	int i = 0;
  8.1884 +
  8.1885 +	/*
  8.1886 +	 * The P4 platform supports up to 256 APIC IDs on two separate APIC 
  8.1887 +	 * buses (one for LAPICs, one for IOAPICs), where predecessors only 
  8.1888 +	 * supports up to 16 on one shared APIC bus.
  8.1889 +	 * 
  8.1890 +	 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
  8.1891 +	 *      advantage of new APIC bus architecture.
  8.1892 +	 */
  8.1893 +
  8.1894 +	if (physids_empty(apic_id_map))
  8.1895 +		apic_id_map = phys_cpu_present_map;
  8.1896 +
  8.1897 +	spin_lock_irqsave(&ioapic_lock, flags);
  8.1898 +	reg_00.raw = io_apic_read(ioapic, 0);
  8.1899 +	spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1900 +
  8.1901 +	if (apic_id >= IO_APIC_MAX_ID) {
  8.1902 +		apic_printk(APIC_QUIET, KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
  8.1903 +			"%d\n", ioapic, apic_id, reg_00.bits.ID);
  8.1904 +		apic_id = reg_00.bits.ID;
  8.1905 +	}
  8.1906 +
  8.1907 +	/*
  8.1908 +	 * Every APIC in a system must have a unique ID or we get lots of nice 
  8.1909 +	 * 'stuck on smp_invalidate_needed IPI wait' messages.
  8.1910 +	 */
  8.1911 +	if (physid_isset(apic_id, apic_id_map)) {
  8.1912 +
  8.1913 +		for (i = 0; i < IO_APIC_MAX_ID; i++) {
  8.1914 +			if (!physid_isset(i, apic_id_map))
  8.1915 +				break;
  8.1916 +		}
  8.1917 +
  8.1918 +		if (i == IO_APIC_MAX_ID)
  8.1919 +			panic("Max apic_id exceeded!\n");
  8.1920 +
  8.1921 +		apic_printk(APIC_VERBOSE, KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
  8.1922 +			"trying %d\n", ioapic, apic_id, i);
  8.1923 +
  8.1924 +		apic_id = i;
  8.1925 +	} 
  8.1926 +
  8.1927 +	physid_set(apic_id, apic_id_map);
  8.1928 +
  8.1929 +	if (reg_00.bits.ID != apic_id) {
  8.1930 +		reg_00.bits.ID = apic_id;
  8.1931 +
  8.1932 +		spin_lock_irqsave(&ioapic_lock, flags);
  8.1933 +		io_apic_write(ioapic, 0, reg_00.raw);
  8.1934 +		reg_00.raw = io_apic_read(ioapic, 0);
  8.1935 +		spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1936 +
  8.1937 +		/* Sanity check */
  8.1938 +		if (reg_00.bits.ID != apic_id)
  8.1939 +			panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
  8.1940 +	}
  8.1941 +
  8.1942 +	apic_printk(APIC_VERBOSE,KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
  8.1943 +#endif /* !CONFIG_XEN */
  8.1944 +
  8.1945 +	return apic_id;
  8.1946 +}
  8.1947 +
  8.1948 +
  8.1949 +int __init io_apic_get_version (int ioapic)
  8.1950 +{
  8.1951 +	union IO_APIC_reg_01	reg_01;
  8.1952 +	unsigned long flags;
  8.1953 +
  8.1954 +	spin_lock_irqsave(&ioapic_lock, flags);
  8.1955 +	reg_01.raw = io_apic_read(ioapic, 1);
  8.1956 +	spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1957 +
  8.1958 +	return reg_01.bits.version;
  8.1959 +}
  8.1960 +
  8.1961 +
  8.1962 +int __init io_apic_get_redir_entries (int ioapic)
  8.1963 +{
  8.1964 +	union IO_APIC_reg_01	reg_01;
  8.1965 +	unsigned long flags;
  8.1966 +
  8.1967 +	spin_lock_irqsave(&ioapic_lock, flags);
  8.1968 +	reg_01.raw = io_apic_read(ioapic, 1);
  8.1969 +	spin_unlock_irqrestore(&ioapic_lock, flags);
  8.1970 +
  8.1971 +	return reg_01.bits.entries;
  8.1972 +}
  8.1973 +
  8.1974 +
  8.1975 +int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
  8.1976 +{
  8.1977 +	struct IO_APIC_route_entry entry;
  8.1978 +	unsigned long flags;
  8.1979 +
  8.1980 +	if (!IO_APIC_IRQ(irq)) {
  8.1981 +		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
  8.1982 +			ioapic);
  8.1983 +		return -EINVAL;
  8.1984 +	}
  8.1985 +
  8.1986 +	/*
  8.1987 +	 * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.
  8.1988 +	 * Note that we mask (disable) IRQs now -- these get enabled when the
  8.1989 +	 * corresponding device driver registers for this IRQ.
  8.1990 +	 */
  8.1991 +
  8.1992 +	memset(&entry,0,sizeof(entry));
  8.1993 +
  8.1994 +	entry.delivery_mode = INT_DELIVERY_MODE;
  8.1995 +	entry.dest_mode = INT_DEST_MODE;
  8.1996 +	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
  8.1997 +	entry.trigger = edge_level;
  8.1998 +	entry.polarity = active_high_low;
  8.1999 +	entry.mask = 1;					 /* Disabled (masked) */
  8.2000 +
  8.2001 +	/*
  8.2002 +	 * IRQs < 16 are already in the irq_2_pin[] map
  8.2003 +	 */
  8.2004 +	if (irq >= 16)
  8.2005 +		add_pin_to_irq(irq, ioapic, pin);
  8.2006 +
  8.2007 +	entry.vector = assign_irq_vector(irq);
  8.2008 +
  8.2009 +	apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
  8.2010 +		"IRQ %d Mode:%i Active:%i)\n", ioapic, 
  8.2011 +	       mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
  8.2012 +	       edge_level, active_high_low);
  8.2013 +
  8.2014 +	ioapic_register_intr(irq, entry.vector, edge_level);
  8.2015 +
  8.2016 +	if (!ioapic && (irq < 16))
  8.2017 +		disable_8259A_irq(irq);
  8.2018 +
  8.2019 +	spin_lock_irqsave(&ioapic_lock, flags);
  8.2020 +	io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
  8.2021 +	io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
  8.2022 +	spin_unlock_irqrestore(&ioapic_lock, flags);
  8.2023 +
  8.2024 +	return 0;
  8.2025 +}
  8.2026 +
  8.2027 +#endif /*CONFIG_ACPI_BOOT*/
  8.2028 +
  8.2029 +
  8.2030 +#ifndef CONFIG_XEN
  8.2031 +/*
  8.2032 + * This function currently is only a helper for the i386 smp boot process where
  8.2033 + * we need to reprogram the ioredtbls to cater for the cpus which have come online
  8.2034 + * so mask in all cases should simply be TARGET_CPUS
  8.2035 + */
  8.2036 +void __init setup_ioapic_dest(void)
  8.2037 +{
  8.2038 +	int pin, ioapic, irq, irq_entry;
  8.2039 +
  8.2040 +	if (skip_ioapic_setup == 1)
  8.2041 +		return;
  8.2042 +
  8.2043 +	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
  8.2044 +		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
  8.2045 +			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
  8.2046 +			if (irq_entry == -1)
  8.2047 +				continue;
  8.2048 +			irq = pin_2_irq(irq_entry, ioapic, pin);
  8.2049 +			set_ioapic_affinity_irq(irq, TARGET_CPUS);
  8.2050 +		}
  8.2051 +
  8.2052 +	}
  8.2053 +}
  8.2054 +#endif /* !CONFIG_XEN */
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/mpparse.c	Sat May 21 10:12:11 2005 +0000
     9.3 @@ -0,0 +1,954 @@
     9.4 +/*
     9.5 + *	Intel Multiprocessor Specification 1.1 and 1.4
     9.6 + *	compliant MP-table parsing routines.
     9.7 + *
     9.8 + *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
     9.9 + *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
    9.10 + *
    9.11 + *	Fixes
    9.12 + *		Erich Boleyn	:	MP v1.4 and additional changes.
    9.13 + *		Alan Cox	:	Added EBDA scanning
    9.14 + *		Ingo Molnar	:	various cleanups and rewrites
    9.15 + *		Maciej W. Rozycki:	Bits for default MP configurations
    9.16 + *		Paul Diefenbaugh:	Added full ACPI support
    9.17 + */
    9.18 +
    9.19 +#include <linux/mm.h>
    9.20 +#include <linux/irq.h>
    9.21 +#include <linux/init.h>
    9.22 +#include <linux/delay.h>
    9.23 +#include <linux/config.h>
    9.24 +#include <linux/bootmem.h>
    9.25 +#include <linux/smp_lock.h>
    9.26 +#include <linux/kernel_stat.h>
    9.27 +#include <linux/mc146818rtc.h>
    9.28 +#include <linux/acpi.h>
    9.29 +
    9.30 +#include <asm/smp.h>
    9.31 +#include <asm/mtrr.h>
    9.32 +#include <asm/mpspec.h>
    9.33 +#include <asm/pgalloc.h>
    9.34 +#include <asm/io_apic.h>
    9.35 +#include <asm/proto.h>
    9.36 +
    9.37 +/* Have we found an MP table */
    9.38 +int smp_found_config;
    9.39 +unsigned int __initdata maxcpus = NR_CPUS;
    9.40 +
    9.41 +int acpi_found_madt;
    9.42 +
    9.43 +/*
    9.44 + * Various Linux-internal data structures created from the
    9.45 + * MP-table.
    9.46 + */
    9.47 +int apic_version [MAX_APICS];
    9.48 +unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
    9.49 +int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
    9.50 +cpumask_t pci_bus_to_cpumask [256] = { [0 ... 255] = CPU_MASK_ALL };
    9.51 +
    9.52 +int mp_current_pci_id = 0;
    9.53 +/* I/O APIC entries */
    9.54 +struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
    9.55 +
    9.56 +/* # of MP IRQ source entries */
    9.57 +struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
    9.58 +
    9.59 +/* MP IRQ source entries */
    9.60 +int mp_irq_entries;
    9.61 +
    9.62 +int nr_ioapics;
    9.63 +int pic_mode;
    9.64 +unsigned long mp_lapic_addr = 0;
    9.65 +
    9.66 +
    9.67 +
    9.68 +/* Processor that is doing the boot up */
    9.69 +unsigned int boot_cpu_id = -1U;
    9.70 +/* Internal processor count */
    9.71 +static unsigned int num_processors = 0;
    9.72 +
    9.73 +/* Bitmask of physically existing CPUs */
    9.74 +physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
    9.75 +
    9.76 +/* ACPI MADT entry parsing functions */
    9.77 +#ifdef CONFIG_ACPI_BOOT
    9.78 +extern struct acpi_boot_flags acpi_boot;
    9.79 +#ifdef CONFIG_X86_LOCAL_APIC
    9.80 +extern int acpi_parse_lapic (acpi_table_entry_header *header);
    9.81 +extern int acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header);
    9.82 +extern int acpi_parse_lapic_nmi (acpi_table_entry_header *header);
    9.83 +#endif /*CONFIG_X86_LOCAL_APIC*/
    9.84 +#ifdef CONFIG_X86_IO_APIC
    9.85 +extern int acpi_parse_ioapic (acpi_table_entry_header *header);
    9.86 +#endif /*CONFIG_X86_IO_APIC*/
    9.87 +#endif /*CONFIG_ACPI_BOOT*/
    9.88 +
    9.89 +u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
    9.90 +
    9.91 +
    9.92 +/*
    9.93 + * Intel MP BIOS table parsing routines:
    9.94 + */
    9.95 +
    9.96 +/*
    9.97 + * Checksum an MP configuration block.
    9.98 + */
    9.99 +
   9.100 +static int __init mpf_checksum(unsigned char *mp, int len)
   9.101 +{
   9.102 +	int sum = 0;
   9.103 +
   9.104 +	while (len--)
   9.105 +		sum += *mp++;
   9.106 +
   9.107 +	return sum & 0xFF;
   9.108 +}
   9.109 +
   9.110 +#ifndef CONFIG_XEN
   9.111 +static void __init MP_processor_info (struct mpc_config_processor *m)
   9.112 +{
   9.113 +	int ver;
   9.114 +
   9.115 +	if (!(m->mpc_cpuflag & CPU_ENABLED))
   9.116 +		return;
   9.117 +
   9.118 +	printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n",
   9.119 +		m->mpc_apicid,
   9.120 +	       (m->mpc_cpufeature & CPU_FAMILY_MASK)>>8,
   9.121 +	       (m->mpc_cpufeature & CPU_MODEL_MASK)>>4,
   9.122 +		m->mpc_apicver);
   9.123 +
   9.124 +	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
   9.125 +		Dprintk("    Bootup CPU\n");
   9.126 +		boot_cpu_id = m->mpc_apicid;
   9.127 +	}
   9.128 +	if (num_processors >= NR_CPUS) {
   9.129 +		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
   9.130 +			" Processor ignored.\n", NR_CPUS);
   9.131 +		return;
   9.132 +	}
   9.133 +	if (num_processors >= maxcpus) {
   9.134 +		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
   9.135 +			" Processor ignored.\n", maxcpus);
   9.136 +		return;
   9.137 +	}
   9.138 +
   9.139 +	num_processors++;
   9.140 +
   9.141 +	if (m->mpc_apicid > MAX_APICS) {
   9.142 +		printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
   9.143 +			m->mpc_apicid, MAX_APICS);
   9.144 +		return;
   9.145 +	}
   9.146 +	ver = m->mpc_apicver;
   9.147 +
   9.148 +	physid_set(m->mpc_apicid, phys_cpu_present_map);
   9.149 +	/*
   9.150 +	 * Validate version
   9.151 +	 */
   9.152 +	if (ver == 0x0) {
   9.153 +		printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
   9.154 +		ver = 0x10;
   9.155 +	}
   9.156 +	apic_version[m->mpc_apicid] = ver;
   9.157 +	bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
   9.158 +}
   9.159 +#else
   9.160 +void __init MP_processor_info (struct mpc_config_processor *m)
   9.161 +{
   9.162 +	num_processors++;
   9.163 +}
   9.164 +#endif /* CONFIG_XEN */
   9.165 +
   9.166 +static void __init MP_bus_info (struct mpc_config_bus *m)
   9.167 +{
   9.168 +	char str[7];
   9.169 +
   9.170 +	memcpy(str, m->mpc_bustype, 6);
   9.171 +	str[6] = 0;
   9.172 +	Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
   9.173 +
   9.174 +	if (strncmp(str, "ISA", 3) == 0) {
   9.175 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
   9.176 +	} else if (strncmp(str, "EISA", 4) == 0) {
   9.177 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
   9.178 +	} else if (strncmp(str, "PCI", 3) == 0) {
   9.179 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
   9.180 +		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
   9.181 +		mp_current_pci_id++;
   9.182 +	} else if (strncmp(str, "MCA", 3) == 0) {
   9.183 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
   9.184 +	} else {
   9.185 +		printk(KERN_ERR "Unknown bustype %s\n", str);
   9.186 +	}
   9.187 +}
   9.188 +
   9.189 +static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
   9.190 +{
   9.191 +	if (!(m->mpc_flags & MPC_APIC_USABLE))
   9.192 +		return;
   9.193 +
   9.194 +	printk("I/O APIC #%d Version %d at 0x%X.\n",
   9.195 +		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
   9.196 +	if (nr_ioapics >= MAX_IO_APICS) {
   9.197 +		printk(KERN_ERR "Max # of I/O APICs (%d) exceeded (found %d).\n",
   9.198 +			MAX_IO_APICS, nr_ioapics);
   9.199 +		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
   9.200 +	}
   9.201 +	if (!m->mpc_apicaddr) {
   9.202 +		printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
   9.203 +			" found in MP table, skipping!\n");
   9.204 +		return;
   9.205 +	}
   9.206 +	mp_ioapics[nr_ioapics] = *m;
   9.207 +	nr_ioapics++;
   9.208 +}
   9.209 +
   9.210 +static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
   9.211 +{
   9.212 +	mp_irqs [mp_irq_entries] = *m;
   9.213 +	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
   9.214 +		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
   9.215 +			m->mpc_irqtype, m->mpc_irqflag & 3,
   9.216 +			(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
   9.217 +			m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
   9.218 +	if (++mp_irq_entries == MAX_IRQ_SOURCES)
   9.219 +		panic("Max # of irq sources exceeded!!\n");
   9.220 +}
   9.221 +
   9.222 +static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
   9.223 +{
   9.224 +	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
   9.225 +		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
   9.226 +			m->mpc_irqtype, m->mpc_irqflag & 3,
   9.227 +			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
   9.228 +			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
   9.229 +	/*
   9.230 +	 * Well it seems all SMP boards in existence
   9.231 +	 * use ExtINT/LVT1 == LINT0 and
   9.232 +	 * NMI/LVT2 == LINT1 - the following check
   9.233 +	 * will show us if this assumptions is false.
   9.234 +	 * Until then we do not have to add baggage.
   9.235 +	 */
   9.236 +	if ((m->mpc_irqtype == mp_ExtINT) &&
   9.237 +		(m->mpc_destapiclint != 0))
   9.238 +			BUG();
   9.239 +	if ((m->mpc_irqtype == mp_NMI) &&
   9.240 +		(m->mpc_destapiclint != 1))
   9.241 +			BUG();
   9.242 +}
   9.243 +
   9.244 +/*
   9.245 + * Read/parse the MPC
   9.246 + */
   9.247 +
   9.248 +static int __init smp_read_mpc(struct mp_config_table *mpc)
   9.249 +{
   9.250 +	char str[16];
   9.251 +	int count=sizeof(*mpc);
   9.252 +	unsigned char *mpt=((unsigned char *)mpc)+count;
   9.253 +
   9.254 +	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
   9.255 +		printk("SMP mptable: bad signature [%c%c%c%c]!\n",
   9.256 +			mpc->mpc_signature[0],
   9.257 +			mpc->mpc_signature[1],
   9.258 +			mpc->mpc_signature[2],
   9.259 +			mpc->mpc_signature[3]);
   9.260 +		return 0;
   9.261 +	}
   9.262 +	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
   9.263 +		printk("SMP mptable: checksum error!\n");
   9.264 +		return 0;
   9.265 +	}
   9.266 +	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
   9.267 +		printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
   9.268 +			mpc->mpc_spec);
   9.269 +		return 0;
   9.270 +	}
   9.271 +	if (!mpc->mpc_lapic) {
   9.272 +		printk(KERN_ERR "SMP mptable: null local APIC address!\n");
   9.273 +		return 0;
   9.274 +	}
   9.275 +	memcpy(str,mpc->mpc_oem,8);
   9.276 +	str[8]=0;
   9.277 +	printk(KERN_INFO "OEM ID: %s ",str);
   9.278 +
   9.279 +	memcpy(str,mpc->mpc_productid,12);
   9.280 +	str[12]=0;
   9.281 +	printk(KERN_INFO "Product ID: %s ",str);
   9.282 +
   9.283 +	printk(KERN_INFO "APIC at: 0x%X\n",mpc->mpc_lapic);
   9.284 +
   9.285 +	/* save the local APIC address, it might be non-default */
   9.286 +	if (!acpi_lapic)
   9.287 +	mp_lapic_addr = mpc->mpc_lapic;
   9.288 +
   9.289 +	/*
   9.290 +	 *	Now process the configuration blocks.
   9.291 +	 */
   9.292 +	while (count < mpc->mpc_length) {
   9.293 +		switch(*mpt) {
   9.294 +			case MP_PROCESSOR:
   9.295 +			{
   9.296 +				struct mpc_config_processor *m=
   9.297 +					(struct mpc_config_processor *)mpt;
   9.298 +				if (!acpi_lapic)
   9.299 +				MP_processor_info(m);
   9.300 +				mpt += sizeof(*m);
   9.301 +				count += sizeof(*m);
   9.302 +				break;
   9.303 +			}
   9.304 +			case MP_BUS:
   9.305 +			{
   9.306 +				struct mpc_config_bus *m=
   9.307 +					(struct mpc_config_bus *)mpt;
   9.308 +				MP_bus_info(m);
   9.309 +				mpt += sizeof(*m);
   9.310 +				count += sizeof(*m);
   9.311 +				break;
   9.312 +			}
   9.313 +			case MP_IOAPIC:
   9.314 +			{
   9.315 +				struct mpc_config_ioapic *m=
   9.316 +					(struct mpc_config_ioapic *)mpt;
   9.317 +				MP_ioapic_info(m);
   9.318 +				mpt+=sizeof(*m);
   9.319 +				count+=sizeof(*m);
   9.320 +				break;
   9.321 +			}
   9.322 +			case MP_INTSRC:
   9.323 +			{
   9.324 +				struct mpc_config_intsrc *m=
   9.325 +					(struct mpc_config_intsrc *)mpt;
   9.326 +
   9.327 +				MP_intsrc_info(m);
   9.328 +				mpt+=sizeof(*m);
   9.329 +				count+=sizeof(*m);
   9.330 +				break;
   9.331 +			}
   9.332 +			case MP_LINTSRC:
   9.333 +			{
   9.334 +				struct mpc_config_lintsrc *m=
   9.335 +					(struct mpc_config_lintsrc *)mpt;
   9.336 +				MP_lintsrc_info(m);
   9.337 +				mpt+=sizeof(*m);
   9.338 +				count+=sizeof(*m);
   9.339 +				break;
   9.340 +			}
   9.341 +		}
   9.342 +	}
   9.343 +	clustered_apic_check();
   9.344 +	if (!num_processors)
   9.345 +		printk(KERN_ERR "SMP mptable: no processors registered!\n");
   9.346 +	return num_processors;
   9.347 +}
   9.348 +
   9.349 +static int __init ELCR_trigger(unsigned int irq)
   9.350 +{
   9.351 +	unsigned int port;
   9.352 +
   9.353 +	port = 0x4d0 + (irq >> 3);
   9.354 +	return (inb(port) >> (irq & 7)) & 1;
   9.355 +}
   9.356 +
   9.357 +static void __init construct_default_ioirq_mptable(int mpc_default_type)
   9.358 +{
   9.359 +	struct mpc_config_intsrc intsrc;
   9.360 +	int i;
   9.361 +	int ELCR_fallback = 0;
   9.362 +
   9.363 +	intsrc.mpc_type = MP_INTSRC;
   9.364 +	intsrc.mpc_irqflag = 0;			/* conforming */
   9.365 +	intsrc.mpc_srcbus = 0;
   9.366 +	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
   9.367 +
   9.368 +	intsrc.mpc_irqtype = mp_INT;
   9.369 +
   9.370 +	/*
   9.371 +	 *  If true, we have an ISA/PCI system with no IRQ entries
   9.372 +	 *  in the MP table. To prevent the PCI interrupts from being set up
   9.373 +	 *  incorrectly, we try to use the ELCR. The sanity check to see if
   9.374 +	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
   9.375 +	 *  never be level sensitive, so we simply see if the ELCR agrees.
   9.376 +	 *  If it does, we assume it's valid.
   9.377 +	 */
   9.378 +	if (mpc_default_type == 5) {
   9.379 +		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
   9.380 +
   9.381 +		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
   9.382 +			printk(KERN_ERR "ELCR contains invalid data... not using ELCR\n");
   9.383 +		else {
   9.384 +			printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
   9.385 +			ELCR_fallback = 1;
   9.386 +		}
   9.387 +	}
   9.388 +
   9.389 +	for (i = 0; i < 16; i++) {
   9.390 +		switch (mpc_default_type) {
   9.391 +		case 2:
   9.392 +			if (i == 0 || i == 13)
   9.393 +				continue;	/* IRQ0 & IRQ13 not connected */
   9.394 +			/* fall through */
   9.395 +		default:
   9.396 +			if (i == 2)
   9.397 +				continue;	/* IRQ2 is never connected */
   9.398 +		}
   9.399 +
   9.400 +		if (ELCR_fallback) {
   9.401 +			/*
   9.402 +			 *  If the ELCR indicates a level-sensitive interrupt, we
   9.403 +			 *  copy that information over to the MP table in the
   9.404 +			 *  irqflag field (level sensitive, active high polarity).
   9.405 +			 */
   9.406 +			if (ELCR_trigger(i))
   9.407 +				intsrc.mpc_irqflag = 13;
   9.408 +			else
   9.409 +				intsrc.mpc_irqflag = 0;
   9.410 +		}
   9.411 +
   9.412 +		intsrc.mpc_srcbusirq = i;
   9.413 +		intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */
   9.414 +		MP_intsrc_info(&intsrc);
   9.415 +	}
   9.416 +
   9.417 +	intsrc.mpc_irqtype = mp_ExtINT;
   9.418 +	intsrc.mpc_srcbusirq = 0;
   9.419 +	intsrc.mpc_dstirq = 0;				/* 8259A to INTIN0 */
   9.420 +	MP_intsrc_info(&intsrc);
   9.421 +}
   9.422 +
   9.423 +static inline void __init construct_default_ISA_mptable(int mpc_default_type)
   9.424 +{
   9.425 +	struct mpc_config_processor processor;
   9.426 +	struct mpc_config_bus bus;
   9.427 +	struct mpc_config_ioapic ioapic;
   9.428 +	struct mpc_config_lintsrc lintsrc;
   9.429 +	int linttypes[2] = { mp_ExtINT, mp_NMI };
   9.430 +	int i;
   9.431 +
   9.432 +	/*
   9.433 +	 * local APIC has default address
   9.434 +	 */
   9.435 +	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
   9.436 +
   9.437 +	/*
   9.438 +	 * 2 CPUs, numbered 0 & 1.
   9.439 +	 */
   9.440 +	processor.mpc_type = MP_PROCESSOR;
   9.441 +	/* Either an integrated APIC or a discrete 82489DX. */
   9.442 +	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
   9.443 +	processor.mpc_cpuflag = CPU_ENABLED;
   9.444 +	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
   9.445 +				   (boot_cpu_data.x86_model << 4) |
   9.446 +				   boot_cpu_data.x86_mask;
   9.447 +	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
   9.448 +	processor.mpc_reserved[0] = 0;
   9.449 +	processor.mpc_reserved[1] = 0;
   9.450 +	for (i = 0; i < 2; i++) {
   9.451 +		processor.mpc_apicid = i;
   9.452 +		MP_processor_info(&processor);
   9.453 +	}
   9.454 +
   9.455 +	bus.mpc_type = MP_BUS;
   9.456 +	bus.mpc_busid = 0;
   9.457 +	switch (mpc_default_type) {
   9.458 +		default:
   9.459 +			printk(KERN_ERR "???\nUnknown standard configuration %d\n",
   9.460 +				mpc_default_type);
   9.461 +			/* fall through */
   9.462 +		case 1:
   9.463 +		case 5:
   9.464 +			memcpy(bus.mpc_bustype, "ISA   ", 6);
   9.465 +			break;
   9.466 +		case 2:
   9.467 +		case 6:
   9.468 +		case 3:
   9.469 +			memcpy(bus.mpc_bustype, "EISA  ", 6);
   9.470 +			break;
   9.471 +		case 4:
   9.472 +		case 7:
   9.473 +			memcpy(bus.mpc_bustype, "MCA   ", 6);
   9.474 +	}
   9.475 +	MP_bus_info(&bus);
   9.476 +	if (mpc_default_type > 4) {
   9.477 +		bus.mpc_busid = 1;
   9.478 +		memcpy(bus.mpc_bustype, "PCI   ", 6);
   9.479 +		MP_bus_info(&bus);
   9.480 +	}
   9.481 +
   9.482 +	ioapic.mpc_type = MP_IOAPIC;
   9.483 +	ioapic.mpc_apicid = 2;
   9.484 +	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
   9.485 +	ioapic.mpc_flags = MPC_APIC_USABLE;
   9.486 +	ioapic.mpc_apicaddr = 0xFEC00000;
   9.487 +	MP_ioapic_info(&ioapic);
   9.488 +
   9.489 +	/*
   9.490 +	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
   9.491 +	 */
   9.492 +	construct_default_ioirq_mptable(mpc_default_type);
   9.493 +
   9.494 +	lintsrc.mpc_type = MP_LINTSRC;
   9.495 +	lintsrc.mpc_irqflag = 0;		/* conforming */
   9.496 +	lintsrc.mpc_srcbusid = 0;
   9.497 +	lintsrc.mpc_srcbusirq = 0;
   9.498 +	lintsrc.mpc_destapic = MP_APIC_ALL;
   9.499 +	for (i = 0; i < 2; i++) {
   9.500 +		lintsrc.mpc_irqtype = linttypes[i];
   9.501 +		lintsrc.mpc_destapiclint = i;
   9.502 +		MP_lintsrc_info(&lintsrc);
   9.503 +	}
   9.504 +}
   9.505 +
   9.506 +static struct intel_mp_floating *mpf_found;
   9.507 +
   9.508 +/*
   9.509 + * Scan the memory blocks for an SMP configuration block.
   9.510 + */
   9.511 +void __init get_smp_config (void)
   9.512 +{
   9.513 +	struct intel_mp_floating *mpf = mpf_found;
   9.514 +
   9.515 +	/*
   9.516 + 	 * ACPI may be used to obtain the entire SMP configuration or just to 
   9.517 + 	 * enumerate/configure processors (CONFIG_ACPI_BOOT).  Note that 
   9.518 + 	 * ACPI supports both logical (e.g. Hyper-Threading) and physical 
   9.519 + 	 * processors, where MPS only supports physical.
   9.520 + 	 */
   9.521 + 	if (acpi_lapic && acpi_ioapic) {
   9.522 + 		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
   9.523 + 		return;
   9.524 +	}
   9.525 + 	else if (acpi_lapic)
   9.526 + 		printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
   9.527 +
   9.528 +	printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
   9.529 +	if (mpf->mpf_feature2 & (1<<7)) {
   9.530 +		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
   9.531 +		pic_mode = 1;
   9.532 +	} else {
   9.533 +		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
   9.534 +		pic_mode = 0;
   9.535 +	}
   9.536 +
   9.537 +	/*
   9.538 +	 * Now see if we need to read further.
   9.539 +	 */
   9.540 +	if (mpf->mpf_feature1 != 0) {
   9.541 +
   9.542 +		printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
   9.543 +		construct_default_ISA_mptable(mpf->mpf_feature1);
   9.544 +
   9.545 +	} else if (mpf->mpf_physptr) {
   9.546 +
   9.547 +		/*
   9.548 +		 * Read the physical hardware table.  Anything here will
   9.549 +		 * override the defaults.
   9.550 +		 */
   9.551 + 		if (!smp_read_mpc(isa_bus_to_virt(mpf->mpf_physptr))) {
   9.552 +			smp_found_config = 0;
   9.553 +			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
   9.554 +			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
   9.555 +			return;
   9.556 +		}
   9.557 +		/*
   9.558 +		 * If there are no explicit MP IRQ entries, then we are
   9.559 +		 * broken.  We set up most of the low 16 IO-APIC pins to
   9.560 +		 * ISA defaults and hope it will work.
   9.561 +		 */
   9.562 +		if (!mp_irq_entries) {
   9.563 +			struct mpc_config_bus bus;
   9.564 +
   9.565 +			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
   9.566 +
   9.567 +			bus.mpc_type = MP_BUS;
   9.568 +			bus.mpc_busid = 0;
   9.569 +			memcpy(bus.mpc_bustype, "ISA   ", 6);
   9.570 +			MP_bus_info(&bus);
   9.571 +
   9.572 +			construct_default_ioirq_mptable(0);
   9.573 +		}
   9.574 +
   9.575 +	} else
   9.576 +		BUG();
   9.577 +
   9.578 +	printk(KERN_INFO "Processors: %d\n", num_processors);
   9.579 +	/*
   9.580 +	 * Only use the first configuration found.
   9.581 +	 */
   9.582 +}
   9.583 +
   9.584 +static int __init smp_scan_config (unsigned long base, unsigned long length)
   9.585 +{
   9.586 +	extern void __bad_mpf_size(void); 
   9.587 +	unsigned int *bp = isa_bus_to_virt(base);
   9.588 +	struct intel_mp_floating *mpf;
   9.589 +
   9.590 +	Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
   9.591 +	if (sizeof(*mpf) != 16)
   9.592 +		__bad_mpf_size();
   9.593 +
   9.594 +	while (length > 0) {
   9.595 +		mpf = (struct intel_mp_floating *)bp;
   9.596 +		if ((*bp == SMP_MAGIC_IDENT) &&
   9.597 +			(mpf->mpf_length == 1) &&
   9.598 +			!mpf_checksum((unsigned char *)bp, 16) &&
   9.599 +			((mpf->mpf_specification == 1)
   9.600 +				|| (mpf->mpf_specification == 4)) ) {
   9.601 +
   9.602 +			smp_found_config = 1;
   9.603 +			mpf_found = mpf;
   9.604 +			return 1;
   9.605 +		}
   9.606 +		bp += 4;
   9.607 +		length -= 16;
   9.608 +	}
   9.609 +	return 0;
   9.610 +}
   9.611 +
   9.612 +void __init find_intel_smp (void)
   9.613 +{
   9.614 +	unsigned int address;
   9.615 +
   9.616 +	/*
   9.617 +	 * FIXME: Linux assumes you have 640K of base ram..
   9.618 +	 * this continues the error...
   9.619 +	 *
   9.620 +	 * 1) Scan the bottom 1K for a signature
   9.621 +	 * 2) Scan the top 1K of base RAM
   9.622 +	 * 3) Scan the 64K of bios
   9.623 +	 */
   9.624 +	if (smp_scan_config(0x0,0x400) ||
   9.625 +		smp_scan_config(639*0x400,0x400) ||
   9.626 +			smp_scan_config(0xF0000,0x10000))
   9.627 +		return;
   9.628 +	/*
   9.629 +	 * If it is an SMP machine we should know now, unless the
   9.630 +	 * configuration is in an EISA/MCA bus machine with an
   9.631 +	 * extended bios data area.
   9.632 +	 *
   9.633 +	 * there is a real-mode segmented pointer pointing to the
   9.634 +	 * 4K EBDA area at 0x40E, calculate and scan it here.
   9.635 +	 *
   9.636 +	 * NOTE! There are Linux loaders that will corrupt the EBDA
   9.637 +	 * area, and as such this kind of SMP config may be less
   9.638 +	 * trustworthy, simply because the SMP table may have been
   9.639 +	 * stomped on during early boot. These loaders are buggy and
   9.640 +	 * should be fixed.
   9.641 +	 */
   9.642 +
   9.643 +	address = *(unsigned short *)phys_to_virt(0x40E);
   9.644 +	address <<= 4;
   9.645 +	if (smp_scan_config(address, 0x1000))
   9.646 +		return;
   9.647 +
   9.648 +	/* If we have come this far, we did not find an MP table  */
   9.649 +	 printk(KERN_INFO "No mptable found.\n");
   9.650 +}
   9.651 +
   9.652 +/*
   9.653 + * - Intel MP Configuration Table
   9.654 + */
   9.655 +void __init find_smp_config (void)
   9.656 +{
   9.657 +#ifdef CONFIG_X86_LOCAL_APIC
   9.658 +	find_intel_smp();
   9.659 +#endif
   9.660 +}
   9.661 +
   9.662 +
   9.663 +/* --------------------------------------------------------------------------
   9.664 +                            ACPI-based MP Configuration
   9.665 +   -------------------------------------------------------------------------- */
   9.666 +
   9.667 +#ifdef CONFIG_ACPI_BOOT
   9.668 +
   9.669 +void __init mp_register_lapic_address (
   9.670 +	u64			address)
   9.671 +{
   9.672 +#ifndef CONFIG_XEN
   9.673 +	mp_lapic_addr = (unsigned long) address;
   9.674 +
   9.675 +	if (boot_cpu_id == -1U)
   9.676 +		boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
   9.677 +
   9.678 +	Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
   9.679 +#endif
   9.680 +}
   9.681 +
   9.682 +
   9.683 +void __init mp_register_lapic (
   9.684 +	u8			id, 
   9.685 +	u8			enabled)
   9.686 +{
   9.687 +	struct mpc_config_processor processor;
   9.688 +	int			boot_cpu = 0;
   9.689 +	
   9.690 +	if (id >= MAX_APICS) {
   9.691 +		printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
   9.692 +			id, MAX_APICS);
   9.693 +		return;
   9.694 +	}
   9.695 +
   9.696 +	if (id == boot_cpu_physical_apicid)
   9.697 +		boot_cpu = 1;
   9.698 +
   9.699 +#ifndef CONFIG_XEN
   9.700 +	processor.mpc_type = MP_PROCESSOR;
   9.701 +	processor.mpc_apicid = id;
   9.702 +	processor.mpc_apicver = 0x10; /* TBD: lapic version */
   9.703 +	processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
   9.704 +	processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
   9.705 +	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | 
   9.706 +		(boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
   9.707 +	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
   9.708 +	processor.mpc_reserved[0] = 0;
   9.709 +	processor.mpc_reserved[1] = 0;
   9.710 +#endif
   9.711 +
   9.712 +	MP_processor_info(&processor);
   9.713 +}
   9.714 +
   9.715 +#ifdef CONFIG_X86_IO_APIC
   9.716 +
   9.717 +#define MP_ISA_BUS		0
   9.718 +#define MP_MAX_IOAPIC_PIN	127
   9.719 +
   9.720 +struct mp_ioapic_routing {
   9.721 +	int			apic_id;
   9.722 +	int			gsi_start;
   9.723 +	int			gsi_end;
   9.724 +	u32			pin_programmed[4];
   9.725 +} mp_ioapic_routing[MAX_IO_APICS];
   9.726 +
   9.727 +
   9.728 +static int mp_find_ioapic (
   9.729 +	int			gsi)
   9.730 +{
   9.731 +	int			i = 0;
   9.732 +
   9.733 +	/* Find the IOAPIC that manages this GSI. */
   9.734 +	for (i = 0; i < nr_ioapics; i++) {
   9.735 +		if ((gsi >= mp_ioapic_routing[i].gsi_start)
   9.736 +			&& (gsi <= mp_ioapic_routing[i].gsi_end))
   9.737 +			return i;
   9.738 +	}
   9.739 +
   9.740 +	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
   9.741 +
   9.742 +	return -1;
   9.743 +}
   9.744 +	
   9.745 +
   9.746 +void __init mp_register_ioapic (
   9.747 +	u8			id, 
   9.748 +	u32			address,
   9.749 +	u32			gsi_base)
   9.750 +{
   9.751 +	int			idx = 0;
   9.752 +
   9.753 +	if (nr_ioapics >= MAX_IO_APICS) {
   9.754 +		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
   9.755 +			"(found %d)\n", MAX_IO_APICS, nr_ioapics);
   9.756 +		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
   9.757 +	}
   9.758 +	if (!address) {
   9.759 +		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
   9.760 +			" found in MADT table, skipping!\n");
   9.761 +		return;
   9.762 +	}
   9.763 +
   9.764 +	idx = nr_ioapics++;
   9.765 +
   9.766 +	mp_ioapics[idx].mpc_type = MP_IOAPIC;
   9.767 +	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
   9.768 +	mp_ioapics[idx].mpc_apicaddr = address;
   9.769 +
   9.770 +	mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
   9.771 +	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
   9.772 +	
   9.773 +	/* 
   9.774 +	 * Build basic IRQ lookup table to facilitate gsi->io_apic lookups
   9.775 +	 * and to prevent reprogramming of IOAPIC pins (PCI IRQs).
   9.776 +	 */
   9.777 +	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
   9.778 +	mp_ioapic_routing[idx].gsi_start = gsi_base;
   9.779 +	mp_ioapic_routing[idx].gsi_end = gsi_base + 
   9.780 +		io_apic_get_redir_entries(idx);
   9.781 +
   9.782 +	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
   9.783 +		"GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, 
   9.784 +		mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
   9.785 +		mp_ioapic_routing[idx].gsi_start,
   9.786 +		mp_ioapic_routing[idx].gsi_end);
   9.787 +
   9.788 +	return;
   9.789 +}
   9.790 +
   9.791 +
   9.792 +void __init mp_override_legacy_irq (
   9.793 +	u8			bus_irq,
   9.794 +	u8			polarity, 
   9.795 +	u8			trigger, 
   9.796 +	u32			gsi)
   9.797 +{
   9.798 +	struct mpc_config_intsrc intsrc;
   9.799 +	int			ioapic = -1;
   9.800 +	int			pin = -1;
   9.801 +
   9.802 +	/* 
   9.803 +	 * Convert 'gsi' to 'ioapic.pin'.
   9.804 +	 */
   9.805 +	ioapic = mp_find_ioapic(gsi);
   9.806 +	if (ioapic < 0)
   9.807 +		return;
   9.808 +	pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
   9.809 +
   9.810 +	/*
   9.811 +	 * TBD: This check is for faulty timer entries, where the override
   9.812 +	 *      erroneously sets the trigger to level, resulting in a HUGE 
   9.813 +	 *      increase of timer interrupts!
   9.814 +	 */
   9.815 +	if ((bus_irq == 0) && (trigger == 3))
   9.816 +		trigger = 1;
   9.817 +
   9.818 +	intsrc.mpc_type = MP_INTSRC;
   9.819 +	intsrc.mpc_irqtype = mp_INT;
   9.820 +	intsrc.mpc_irqflag = (trigger << 2) | polarity;
   9.821 +	intsrc.mpc_srcbus = MP_ISA_BUS;
   9.822 +	intsrc.mpc_srcbusirq = bus_irq;				       /* IRQ */
   9.823 +	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;	   /* APIC ID */
   9.824 +	intsrc.mpc_dstirq = pin;				    /* INTIN# */
   9.825 +
   9.826 +	Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n", 
   9.827 +		intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
   9.828 +		(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
   9.829 +		intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
   9.830 +
   9.831 +	mp_irqs[mp_irq_entries] = intsrc;
   9.832 +	if (++mp_irq_entries == MAX_IRQ_SOURCES)
   9.833 +		panic("Max # of irq sources exceeded!\n");
   9.834 +
   9.835 +	return;
   9.836 +}
   9.837 +
   9.838 +
   9.839 +void __init mp_config_acpi_legacy_irqs (void)
   9.840 +{
   9.841 +	struct mpc_config_intsrc intsrc;
   9.842 +	int			i = 0;
   9.843 +	int			ioapic = -1;
   9.844 +
   9.845 +	/* 
   9.846 +	 * Fabricate the legacy ISA bus (bus #31).
   9.847 +	 */
   9.848 +	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
   9.849 +	Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
   9.850 +
   9.851 +	/* 
   9.852 +	 * Locate the IOAPIC that manages the ISA IRQs (0-15). 
   9.853 +	 */
   9.854 +	ioapic = mp_find_ioapic(0);
   9.855 +	if (ioapic < 0)
   9.856 +		return;
   9.857 +
   9.858 +	intsrc.mpc_type = MP_INTSRC;
   9.859 +	intsrc.mpc_irqflag = 0;					/* Conforming */
   9.860 +	intsrc.mpc_srcbus = MP_ISA_BUS;
   9.861 +	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
   9.862 +
   9.863 +	/* 
   9.864 +	 * Use the default configuration for the IRQs 0-15.  Unless
   9.865 +	 * overridden by (MADT) interrupt source override entries.
   9.866 +	 */
   9.867 +	for (i = 0; i < 16; i++) {
   9.868 +		int idx;
   9.869 +
   9.870 +		for (idx = 0; idx < mp_irq_entries; idx++) {
   9.871 +			struct mpc_config_intsrc *irq = mp_irqs + idx;
   9.872 +
   9.873 +			/* Do we already have a mapping for this ISA IRQ? */
   9.874 +			if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
   9.875 +				break;
   9.876 +
   9.877 +			/* Do we already have a mapping for this IOAPIC pin */
   9.878 +			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
   9.879 +				(irq->mpc_dstirq == i))
   9.880 +				break;
   9.881 +		}
   9.882 +
   9.883 +		if (idx != mp_irq_entries) {
   9.884 +			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
   9.885 +			continue;			/* IRQ already used */
   9.886 +		}
   9.887 +
   9.888 +		intsrc.mpc_irqtype = mp_INT;
   9.889 +		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
   9.890 +		intsrc.mpc_dstirq = i;
   9.891 +
   9.892 +		Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
   9.893 +			"%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
   9.894 +			(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
   9.895 +			intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, 
   9.896 +			intsrc.mpc_dstirq);
   9.897 +
   9.898 +		mp_irqs[mp_irq_entries] = intsrc;
   9.899 +		if (++mp_irq_entries == MAX_IRQ_SOURCES)
   9.900 +			panic("Max # of irq sources exceeded!\n");
   9.901 +	}
   9.902 +
   9.903 +	return;
   9.904 +}
   9.905 +
   9.906 +int mp_register_gsi(u32 gsi, int edge_level, int active_high_low)
   9.907 +{
   9.908 +	int			ioapic = -1;
   9.909 +	int			ioapic_pin = 0;
   9.910 +	int			idx, bit = 0;
   9.911 +
   9.912 +	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
   9.913 +		return gsi;
   9.914 +
   9.915 +#ifdef CONFIG_ACPI_BUS
   9.916 +	/* Don't set up the ACPI SCI because it's already set up */
   9.917 +	if (acpi_fadt.sci_int == gsi)
   9.918 +		return gsi;
   9.919 +#endif
   9.920 +
   9.921 +	ioapic = mp_find_ioapic(gsi);
   9.922 +	if (ioapic < 0) {
   9.923 +		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
   9.924 +		return gsi;
   9.925 +	}
   9.926 +
   9.927 +	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
   9.928 +
   9.929 +	/* 
   9.930 +	 * Avoid pin reprogramming.  PRTs typically include entries  
   9.931 +	 * with redundant pin->gsi mappings (but unique PCI devices);
   9.932 +	 * we only program the IOAPIC on the first.
   9.933 +	 */
   9.934 +	bit = ioapic_pin % 32;
   9.935 +	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
   9.936 +	if (idx > 3) {
   9.937 +		printk(KERN_ERR "Invalid reference to IOAPIC pin "
   9.938 +			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
   9.939 +			ioapic_pin);
   9.940 +		return gsi;
   9.941 +	}
   9.942 +	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
   9.943 +		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
   9.944 +			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
   9.945 +		return gsi;
   9.946 +	}
   9.947 +
   9.948 +	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
   9.949 +
   9.950 +	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
   9.951 +		edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
   9.952 +		active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
   9.953 +	return gsi;
   9.954 +}
   9.955 +
   9.956 +#endif /*CONFIG_X86_IO_APIC*/
   9.957 +#endif /*CONFIG_ACPI_BOOT*/
    10.1 --- a/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/setup.c	Sat May 21 10:09:53 2005 +0000
    10.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/setup.c	Sat May 21 10:12:11 2005 +0000
    10.3 @@ -675,14 +675,6 @@ void __init setup_arch(char **cmdline_p)
    10.4  
    10.5  	init_memory_mapping(0, (end_pfn << PAGE_SHIFT));
    10.6  
    10.7 -#ifdef CONFIG_ACPI_BOOT
    10.8 -	/*
    10.9 -	 * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
   10.10 -	 * Call this early for SRAT node setup.
   10.11 -	 */
   10.12 -	acpi_boot_table_init();
   10.13 -#endif
   10.14 -
   10.15  #ifdef CONFIG_ACPI_NUMA
   10.16  	/*
   10.17  	 * Parse SRAT to discover nodes.
   10.18 @@ -733,12 +725,6 @@ void __init setup_arch(char **cmdline_p)
   10.19          */
   10.20         acpi_reserve_bootmem();
   10.21  #endif
   10.22 -#ifdef CONFIG_X86_LOCAL_APIC
   10.23 -	/*
   10.24 -	 * Find and reserve possible boot-time SMP configuration:
   10.25 -	 */
   10.26 -	find_smp_config();
   10.27 -#endif
   10.28  #ifdef CONFIG_BLK_DEV_INITRD
   10.29          if (xen_start_info.mod_start) {
   10.30                  if (LOADER_TYPE && INITRD_START) {
   10.31 @@ -759,7 +745,12 @@ void __init setup_arch(char **cmdline_p)
   10.32          }
   10.33  #endif
   10.34  	paging_init();
   10.35 -
   10.36 +#ifdef CONFIG_X86_LOCAL_APIC
   10.37 +	/*
   10.38 +	 * Find and reserve possible boot-time SMP configuration:
   10.39 +	 */
   10.40 +	find_smp_config();
   10.41 +#endif
   10.42  	/* Make sure we have a large enough P->M table. */
   10.43  	if (end_pfn > xen_start_info.nr_pages) {
   10.44  		phys_to_machine_mapping = alloc_bootmem(
   10.45 @@ -789,19 +780,26 @@ void __init setup_arch(char **cmdline_p)
   10.46  
   10.47  #ifdef CONFIG_ACPI_BOOT
   10.48  	/*
   10.49 +	 * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
   10.50 +	 * Call this early for SRAT node setup.
   10.51 +	 */
   10.52 +	acpi_boot_table_init();
   10.53 +
   10.54 +	/*
   10.55  	 * Read APIC and some other early information from ACPI tables.
   10.56  	 */
   10.57  	acpi_boot_init();
   10.58  #endif
   10.59 -
   10.60  #ifdef CONFIG_X86_LOCAL_APIC
   10.61  	/*
   10.62  	 * get boot-time SMP configuration:
   10.63  	 */
   10.64  	if (smp_found_config)
   10.65  		get_smp_config();
   10.66 +#ifndef CONFIG_XEN
   10.67  	init_apic_mappings();
   10.68  #endif
   10.69 +#endif
   10.70  
   10.71          /* XXX Disable irqdebug until we have a way to avoid interrupt
   10.72  	 * conflicts. */
    11.1 --- a/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/traps.c	Sat May 21 10:09:53 2005 +0000
    11.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/x86_64/kernel/traps.c	Sat May 21 10:12:11 2005 +0000
    11.3 @@ -389,7 +389,6 @@ static inline void die_if_kernel(const c
    11.4  		die(str, regs, err);
    11.5  }
    11.6  
    11.7 -#if 0
    11.8  void die_nmi(char *str, struct pt_regs *regs)
    11.9  {
   11.10  	oops_begin();
   11.11 @@ -405,7 +404,6 @@ void die_nmi(char *str, struct pt_regs *
   11.12  	oops_end();
   11.13  	do_exit(SIGSEGV);
   11.14  }
   11.15 -#endif
   11.16  
   11.17  static void do_trap(int trapnr, int signr, char *str, 
   11.18  			   struct pt_regs * regs, long error_code, siginfo_t *info)
   11.19 @@ -556,7 +554,6 @@ asmlinkage void do_general_protection(st
   11.20  	}
   11.21  }
   11.22  
   11.23 -#if 0
   11.24  static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
   11.25  {
   11.26  	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
   11.27 @@ -630,7 +627,6 @@ asmlinkage void default_do_nmi(struct pt
   11.28  	outb(0x0f, 0x70);
   11.29  	inb(0x71);		/* dummy */
   11.30  }
   11.31 -#endif
   11.32  
   11.33  asmlinkage void do_int3(struct pt_regs * regs, long error_code)
   11.34  {
    12.1 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/fixmap.h	Sat May 21 10:09:53 2005 +0000
    12.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/fixmap.h	Sat May 21 10:12:11 2005 +0000
    12.3 @@ -18,6 +18,7 @@
    12.4  #include <asm/page.h>
    12.5  #include <asm/vsyscall.h>
    12.6  #include <asm/vsyscall32.h>
    12.7 +#include <asm/acpi.h>
    12.8  
    12.9  /*
   12.10   * Here we define all the compile-time 'special' virtual
   12.11 @@ -46,6 +47,11 @@ enum fixed_addresses {
   12.12  	FIX_IO_APIC_BASE_0,
   12.13  	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
   12.14  #endif
   12.15 +#ifdef CONFIG_ACPI_BOOT
   12.16 +	FIX_ACPI_BEGIN,
   12.17 +	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
   12.18 +	FIX_ACPI_RSDP_PAGE,
   12.19 +#endif
   12.20  	FIX_SHARED_INFO,
   12.21  	FIX_GNTTAB_BEGIN,
   12.22  	FIX_GNTTAB_END = FIX_GNTTAB_BEGIN + NR_GRANT_FRAMES - 1,
    13.1 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h	Sat May 21 10:09:53 2005 +0000
    13.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h	Sat May 21 10:12:11 2005 +0000
    13.3 @@ -44,8 +44,6 @@
    13.4   *
    13.5   *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
    13.6   */
    13.7 -#define SPURIOUS_APIC_VECTOR	0xff
    13.8 -#define ERROR_APIC_VECTOR	0xfe
    13.9  #define INVALIDATE_TLB_VECTOR	0xfd
   13.10  #define RESCHEDULE_VECTOR	0xfc
   13.11  #define CALL_FUNCTION_VECTOR	0xfb
   13.12 @@ -59,6 +57,9 @@
   13.13  #define LOCAL_TIMER_VECTOR	0xef
   13.14  #endif
   13.15  
   13.16 +#define SPURIOUS_APIC_VECTOR	0xff
   13.17 +#define ERROR_APIC_VECTOR	0xfe
   13.18 +
   13.19  /*
   13.20   * First APIC vector available to drivers: (vectors 0x30-0xee)
   13.21   * we start at 0x31 to spread out vectors evenly between priority