[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] Fix xen hang on intel westmere-EP
On Intel westmere-ep(w/ ICH10 chipset), the legacy USB logic will generate SMI consistently. And this will cause system hang under some specified conditions. So we need to disable it during early boot. Signed-off-by: Yang Zhang <yang.z.zhang@xxxxxxxxx> diff -r 0f36c2eec2e1 xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile Thu Jul 28 15:40:54 2011 +0100 +++ b/xen/arch/x86/Makefile Mon Aug 22 16:23:16 2011 +0800 @@ -57,6 +57,7 @@ obj-y += tboot.o obj-y += hpet.o obj-y += xstate.o +obj-y += early_quirks.o obj-$(crash_debug) += gdbstub.o diff -r 0f36c2eec2e1 xen/arch/x86/early_quirks.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/early_quirks.c Mon Aug 22 16:23:16 2011 +0800 @@ -0,0 +1,72 @@ +/* + * arch/x86/early_quirks.c + * + * This code used to workaround the chipset bugs. + * + */ + +#include <xen/init.h> +#include <xen/pci.h> +#include <xen/pci_regs.h> +#include <asm/io.h> + +/* + * For intel ich10 chipset, it has bug on deliver legacy usb + * SMI to CPU and will cause system hang. So we need to disable + * it when booting. + */ +void intel_smi_quirk( + unsigned int bus, unsigned int dev, unsigned int func) { + unsigned int pmbase; + unsigned int smi_ctrl_addr, smi_ctrl_reg; + + /* + * Smi control register reside at pmbase +30h. We need to find + * the pmbase address firstly which located at offset 0x40. + */ + pmbase = pci_conf_read32(bus, dev, func, 0x40); + + smi_ctrl_addr = (pmbase & 0xff80) + 0x30; + smi_ctrl_reg = inl(smi_ctrl_addr); + + /* + *mask bit 3 and bit 17 to disable legacy usb to generate SMI. + */ + smi_ctrl_reg &= ~0x20008; + outl(smi_ctrl_reg, smi_ctrl_addr); +} + +struct chipset { + unsigned int vendor; + unsigned int device; + void (*f)(unsigned int bus, unsigned int dev, unsigned int func); +}; + +static struct chipset early_quirk[] = { + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_ICH10_LPC, intel_smi_quirk}, + {} +}; + +static void check_quirk(unsigned int bus, unsigned int dev, unsigned +int func) { + unsigned int vendor_id, device_id; + int i; + + vendor_id = pci_conf_read16(bus, dev, func, PCI_VENDOR_ID); + device_id = pci_conf_read16(bus, dev, func, PCI_DEVICE_ID); + + for (i = 0; early_quirk[i].f != NULL; i++) + if (early_quirk[i].vendor == vendor_id && + early_quirk[i].device == device_id) + early_quirk[i].f(bus, dev, func); } + +void __init early_quirks(void) +{ + unsigned int dev, func; + + for (dev = 0; dev < 32; dev++) + for (func = 0; func < 8; func++) + check_quirk(0, dev, func); +} diff -r 0f36c2eec2e1 xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Thu Jul 28 15:40:54 2011 +0100 +++ b/xen/arch/x86/setup.c Mon Aug 22 16:23:16 2011 +0800 @@ -1255,6 +1255,8 @@ if ( opt_nosmp ) max_cpus = 0; + early_quirks(); + iommu_setup(); /* setup iommu if available */ smp_prepare_cpus(max_cpus); diff -r 0f36c2eec2e1 xen/include/asm-x86/setup.h --- a/xen/include/asm-x86/setup.h Thu Jul 28 15:40:54 2011 +0100 +++ b/xen/include/asm-x86/setup.h Mon Aug 22 16:23:16 2011 +0800 @@ -12,6 +12,7 @@ void early_cpu_init(void); void early_time_init(void); void early_page_fault(void); +void early_quirks(void); int intel_cpu_init(void); int amd_init_cpu(void); diff -r 0f36c2eec2e1 xen/include/xen/pci_regs.h --- a/xen/include/xen/pci_regs.h Thu Jul 28 15:40:54 2011 +0100 +++ b/xen/include/xen/pci_regs.h Mon Aug 22 16:23:16 2011 +0800 @@ -22,6 +22,9 @@ #ifndef LINUX_PCI_REGS_H #define LINUX_PCI_REGS_H +#define PCI_VENDOR_ID_INTEL 0x8086 +#define PCI_DEVICE_ID_ICH10_LPC 0x3a16 + /* * Under PCI, each device has 256 bytes of configuration address space, * of which the first 64 bytes are standardized as follows: _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |