Module: xenomai-forge Branch: next Commit: 689bc893a0bb245db66b73d0bd124cfbb8fd512f URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=689bc893a0bb245db66b73d0bd124cfbb8fd512f
Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org> Date: Sat Apr 13 22:05:01 2013 +0200 x86: allow SMI control at run-time Having to recompile the kernel when we want to change the settings regarding SMI workaround is not really compatible with distributing pre-compiled kernels. So we make the control possible with two kernel parameters. Allowing to compile out the functionality did not save a lot of room anyway. At this chance, suppress the PCI ids table which was a maintenance burden, any Intel chipset with a PCI-ISA bridge is assumed to allow SMI workaround. By default, the module detects the chipset but does nothing. Setting: - xeno_hal.smi to -1 disables SMI detection - xeno_hal.smi to 1 enables SMI workaround, the parameter xeno_hal.smi_mask controls which bits are masked. If not set, the bit 0 is masked which means SMI are globally disabled. --- include/asm-x86/smi.h | 15 +-- kernel/cobalt/arch/x86/Kconfig | 135 ----------------------------- kernel/cobalt/arch/x86/Makefile | 3 +- kernel/cobalt/arch/x86/smi.c | 179 +++++++-------------------------------- 4 files changed, 36 insertions(+), 296 deletions(-) diff --git a/include/asm-x86/smi.h b/include/asm-x86/smi.h index 959f124..f382bbf 100644 --- a/include/asm-x86/smi.h +++ b/include/asm-x86/smi.h @@ -19,6 +19,9 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef _XENO_ASM_X86_SMI_H +#define _XENO_ASM_X86_SMI_H + #ifndef __KERNEL__ #error "Pure kernel header included from user-space!" #endif @@ -27,16 +30,8 @@ #error "please don't include asm/smi.h directly" #endif -#if defined(CONFIG_XENO_HW_SMI_DETECT) && defined(CONFIG_XENO_HW_SMI_WORKAROUND) void mach_x86_smi_disable(void); void mach_x86_smi_restore(void); -#else /* !CONFIG_XENO_HW_SMI_DETECT || !CONFIG_XENO_HW_SMI_WORKAROUND */ -static inline void mach_x86_smi_disable(void) { } -static inline void mach_x86_smi_restore(void) { } -#endif /* !CONFIG_XENO_HW_SMI_DETECT || !CONFIG_XENO_HW_SMI_WORKAROUND */ - -#ifdef CONFIG_XENO_HW_SMI_DETECT void mach_x86_smi_init(void); -#else /* !CONFIG_XENO_HW_SMI_DETECT */ -static inline void mach_x86_smi_init(void) { } -#endif /* CONFIG_XENO_HW_SMI_DETECT */ + +#endif /* !_XENO_ASM_X86_SMI_64_H */ diff --git a/kernel/cobalt/arch/x86/Kconfig b/kernel/cobalt/arch/x86/Kconfig index 9025fcf..0f5a0b2 100644 --- a/kernel/cobalt/arch/x86/Kconfig +++ b/kernel/cobalt/arch/x86/Kconfig @@ -14,141 +14,6 @@ config XENO_HW_FPU Float-Point Unit on the x86 platform at the following URL: http://www.intel.com/design/intarch/techinfo/Pentium/fpu.htm -menu "SMI workaround" - -config XENO_HW_SMI_DETECT_DISABLE - bool "Disable SMI detection" - default n - help - SMI are System Management Interrupts, generated by Intel ICH - (I/O connector hubs) to allow handling of some specific events; - on systems where they exist, they are the highest priority - interrupts (even higher priority than NMIs). Common SMI sources - are power management, legacy devices emulation by BIOS, SMBus - and TCO watchdog. - - SMI are problematic for Xenomai, because their handling may span - accross hundreds of microseconds, causing unacceptable interrupt - latency. Furthermore, their vectors are stored in some ROM, - and hence may not be altered. - - For this reason, Xenomai contains code to detect chipsets using - SMIs and optionally activate some workarounds to stop SMIs. - - Enabling this option prevents Xenomai from detecting whether - your hardware use SMIs. This option is mostly useful if you know - that your system does not use SMIs and really want to size Xenomai - modules down. The detection code has no run-time space overhead, - and a tiny memory footprint (<200 bytes on x86) - -config XENO_HW_SMI_DETECT - bool - depends on !XENO_HW_SMI_DETECT_DISABLE - default y - -config XENO_HW_SMI_WORKAROUND - depends on XENO_HW_SMI_DETECT - bool "Enable SMI workaround" - default n - help - SMI are System Management Interrupts, generated by Intel ICH - (I/O connector hubs) to allow handling of some specific events; - on systems where they exist, they are the highest priority - interrupts (even higher priority than NMIs). Common SMI sources - are power management, legacy devices emulation by BIOS, SMBus - and TCO watchdog. - - SMI are problematic for Xenomai, because their handling may span - accross hundreds of microseconds, causing unacceptable interrupt - latency. Furthermore, their vectors are stored in some ROM, - and hence may not be altered. - - For this reason, Xenomai contains code to detect chipsets using - SMIs and optionally activate some workarounds to stop SMIs. - Enabling this option cause those workarounds to be activated. - -if XENO_HW_SMI_WORKAROUND - -config XENO_HW_SMI_ALL - bool "Globally disable SMI" - default y - help - This option causes the SMIs to be globally disabled, which avoid - any jitter they could cause with a big drawback: any peripheral or - feature relying on them will stop working when Xenomai is running. - - The alternative is to selectively enable the SMIs sources needed - by your peripherals. The main drawback is that the peripheral - which you need may be the one causing jitter, so that extensive - testing is needed when choosing to not disable SMI globally. - Another drawback is that other unknown SMI sources may exist which - Xenomai can not disable. - - This option causes the SMIs to be globally disabled. - -config XENO_HW_SMI_INTEL_USB2 - bool "Enable Intel-Specific USB2 SMI" - depends on !XENO_HW_SMI_ALL - default n - help - This options enables Intel-specific USB2 SMI logic to cause SMIs. - -config XENO_HW_SMI_LEGACY_USB2 - bool "Enable legacy USB2 SMI" - depends on !XENO_HW_SMI_ALL - default n - help - This options enables legacy USB2 logic to cause SMIs. - -config XENO_HW_SMI_PERIODIC - bool "Enable periodic SMI" - depends on !XENO_HW_SMI_ALL - default n - help - This options enables the ICH to generate a periodic SMI. - -config XENO_HW_SMI_TCO - bool "Enable TCO SMI" - depends on !XENO_HW_SMI_ALL - default n - help - This options enables the TCO logic to generate SMIs. - -config XENO_HW_SMI_MC - bool "Enable microcontroller SMI" - depends on !XENO_HW_SMI_ALL - default n - help - This options enables the ICH to trap access to the - microcontroller range. - -config XENO_HW_SMI_APMC - bool "Enable APM SMI" - depends on !XENO_HW_SMI_ALL - default n - help - This options enables writes to the APM control register to - cause SMIs. - -config XENO_HW_SMI_LEGACY_USB - bool "Enable legacy USB SMI" - depends on !XENO_HW_SMI_ALL - default n - help - This options enables legacy USB circuit to cause SMIs. - -config XENO_HW_SMI_BIOS - bool "Enable ACPI BIOS SMI" - depends on !XENO_HW_SMI_ALL - default n - help - This options enables SMI to be used for communication - between ACPI software and BIOS software. - -endif - -endmenu - endmenu source "kernel/xenomai/nucleus/Kconfig" diff --git a/kernel/cobalt/arch/x86/Makefile b/kernel/cobalt/arch/x86/Makefile index 2001b8e..998f65b 100644 --- a/kernel/cobalt/arch/x86/Makefile +++ b/kernel/cobalt/arch/x86/Makefile @@ -1,6 +1,5 @@ obj-$(CONFIG_XENOMAI) += x86_hal.o -x86_hal-y := machine.o mayday.o thread.o -x86_hal-$(CONFIG_XENO_HW_SMI_DETECT) += smi.o +x86_hal-y := machine.o mayday.o thread.o smi.o ccflags-y := -D__IN_XENOMAI__ -Iinclude/xenomai/cobalt -Iinclude/xenomai diff --git a/kernel/cobalt/arch/x86/smi.c b/kernel/cobalt/arch/x86/smi.c index c78317c..e06734a 100644 --- a/kernel/cobalt/arch/x86/smi.c +++ b/kernel/cobalt/arch/x86/smi.c @@ -29,95 +29,20 @@ #include <asm-generic/xenomai/pci_ids.h> #include <asm/xenomai/machine.h> -static struct pci_device_id smi_pci_tbl[] = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_1)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_5)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_1)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_LPC_MIN+7)}, - {0,}, -}; +#define DEVFN 0xf8 /* device 31, function 0 */ + +#define PMBASE_B0 0x40 +#define PMBASE_B1 0x41 + +#define SMI_CTRL_ADDR 0x30 -/* FIXME: Probably crippled too, need to be checked : - -0x24dc 82801EB (ICH5) LPC Interface Bridge (not a real ID, but exists in the -pci.ids database, ICH5-M ?) -{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12, PCI_ANY_ID, PCI_ANY_ID, }, - -*/ - -#define DEVFN 0xf8 /* device 31, function 0 */ - -#ifdef CONFIG_XENO_HW_SMI_WORKAROUND - -#define PMBASE_B0 0x40 -#define PMBASE_B1 0x41 - -#define SMI_CTRL_ADDR 0x30 -#define SMI_STATUS_ADDR 0x34 -#define SMI_MON_ADDR 0x40 - -/* SMI_EN register: ICH[0](16 bits), ICH[2-5](32 bits) */ -#define INTEL_USB2_EN_BIT (0x01 << 18) /* ICH4, ... */ -#define LEGACY_USB2_EN_BIT (0x01 << 17) /* ICH4, ... */ -#define PERIODIC_EN_BIT (0x01 << 14) /* called 1MIN_ in ICH0 */ -#define TCO_EN_BIT (0x01 << 13) -#define MCSMI_EN_BIT (0x01 << 11) -#define SWSMI_TMR_EN_BIT (0x01 << 6) -#define APMC_EN_BIT (0x01 << 5) -#define SLP_EN_BIT (0x01 << 4) -#define LEGACY_USB_EN_BIT (0x01 << 3) -#define BIOS_EN_BIT (0x01 << 2) -#define GBL_SMI_EN_BIT (0x01) /* This is reset by a PCI reset event! */ - -static const unsigned smi_masked_bits = -#ifdef CONFIG_XENO_HW_SMI_ALL - GBL_SMI_EN_BIT; -#else /* !defined(CONFIG_XENO_HW_SMI_ALL) */ - 0 -#ifndef CONFIG_XENO_HW_SMI_INTEL_USB2 - | INTEL_USB2_EN_BIT -#endif /* !defined(CONFIG_XENO_HW_SMI_INTEL_USB2) */ -#ifndef CONFIG_XENO_HW_SMI_LEGACY_USB2 - | LEGACY_USB2_EN_BIT -#endif /* !defined(CONFIG_XENO_HW_SMI_LEGACY_USB2) */ -#ifndef CONFIG_XENO_HW_SMI_PERIODIC - | PERIODIC_EN_BIT -#endif /* !defined(CONFIG_XENO_HW_SMI_PERIODC) */ -#ifndef CONFIG_XENO_HW_SMI_TCO - | TCO_EN_BIT -#endif /* !defined(CONFIG_XENO_HW_SMI_TCO) */ -#ifndef CONFIG_XENO_HW_SMI_MC - | MCSMI_EN_BIT -#endif /* !defined(CONFIG_XENO_HW_SMI_MCSMI) */ -#ifndef CONFIG_XENO_HW_SMI_APMC - | APMC_EN_BIT -#endif /* !defined(CONFIG_XENO_HW_SMI_APMC) */ -#ifndef CONFIG_XENO_HW_SMI_LEGACY_USB - | LEGACY_USB_EN_BIT -#endif /* !defined(CONFIG_XENO_HW_SMI_LEGACY_USB) */ -#ifndef CONFIG_XENO_HW_SMI_BIOS - | BIOS_EN_BIT -#endif /* !defined(CONFIG_XENO_HW_SMI_BIOS) */ - ; - -#endif /* !defined(CONFIG_XENO_HW_SMI_ALL) */ +static int smi_state; +module_param_named(smi, smi_state, int, 0400); +MODULE_PARM_DESC(smi, "SMI workaround: -1=disable, 0=detect only, 1=enable"); + +static unsigned int smi_masked_bits = 1; /* Global disable bit */ +module_param_named(smi_mask, smi_masked_bits, int, 0400); +MODULE_PARM_DESC(smi_mask, "Set of bits to mask in the SMI control register"); static unsigned int smi_saved_bits; static unsigned short smi_en_addr; @@ -142,7 +67,7 @@ static int smi_reboot(struct notifier_block *nb, ulong event, void *buf) void mach_x86_smi_disable(void) { - if (!smi_en_addr) + if (smi_en_addr == 0) return; smi_saved_bits = inl(smi_en_addr) & smi_masked_bits; @@ -158,7 +83,7 @@ void mach_x86_smi_disable(void) void mach_x86_smi_restore(void) { - if (!smi_en_addr) + if (smi_en_addr == 0) return; printk("Xenomai: SMI configuration restored\n"); @@ -177,79 +102,35 @@ static unsigned short get_smi_en_addr(struct pci_dev *dev) return SMI_CTRL_ADDR + (((byte1 << 1) | (byte0 >> 7)) << 7); // bits 7-15 } -#endif /* CONFIG_XENO_HW_SMI_WORKAROUND */ - void mach_x86_smi_init(void) { struct pci_dev *dev = NULL; - struct pci_device_id *id; + + if (smi_state < 0) + return; /* * Do not use pci_register_driver, pci_enable_device, ... * Just register the used ports. */ - for (id = &smi_pci_tbl[0]; dev == NULL && id->vendor != 0; id++) - dev = pci_get_device(id->vendor, id->device, NULL); + dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); + if (dev == NULL || dev->bus->number || + dev->devfn != DEVFN || dev->vendor != PCI_VENDOR_ID_INTEL) { + pci_dev_put(dev); + return; + } - if (dev == NULL || dev->bus->number || dev->devfn != DEVFN) { + if (smi_state == 0) { + printk("Xenomai: SMI-enabled chipset found, but SMI " + "workaround disabled\n" + " (see xeno_hal.smi parameter). You may encounter\n" + " high interrupt latencies!\n"); pci_dev_put(dev); return; } -#ifdef CONFIG_XENO_HW_SMI_WORKAROUND + printk("Xenomai: SMI-enabled chipset found\n"); smi_en_addr = get_smi_en_addr(dev); -#else /* ! CONFIG_XENO_HW_SMI_WORKAROUND */ - printk - ("Xenomai: SMI-enabled chipset found, but SMI workaround disabled\n" - " (check CONFIG_XENO_HW_SMI_WORKAROUND). You may encounter\n" - " high interrupt latencies!\n"); -#endif /* ! CONFIG_XENO_HW_SMI_WORKAROUND */ pci_dev_put(dev); } - -/* - - FIXME: there are many more SMI sources than those of the SMI_EN - register. From http://www.intel.com/design/chipsets/datashts/252516.htm - there are at least the following other sources : - - pages 377, 386, 388, 389; Power management - register GEN_PMCON1, bit SMI_LOCK, locks GLB_SMI_EN - bits PER_SMI_SEL, allow selection of the periodic SMI - registers PM1_STS, PM1_EN, PM1_CNT bit SCI_EN, if cleared generates SMI - for power management events. - - pages 173, 381, 400; GPIOs - register GPI[0-15]_ROUT allow routing each GPIO to SMI or SCI - register ALT_GP_SMI_EN, ALT_GP_SMI_STS, allow masking SMIs for GPIOs - - pages 184, 188, 402; legacy devices emulation (ATA, floppy, parallel, UARTs, - keyboard). I/O to specified ports may cause events, which can generate an - SMI, depending on registers configuration : - register DEVTRAP_EN, DEVTRAP_STS - BIG FAT WARNING : globally disabling SMI on a box with SATA disks and - SATA controller in "legacy" mode, probably prevents disks from - working. - - pages 382, 383, 400; Monitors ? - seem to be a generic legacy device emulation (like previous), registers - MON[4-7]_FWD_EN, enables forwarding of I/O to LPC - MON[4-7]_TRP_RNG, address of the emulated devices - MON[4-7]_TRP_MSK and MON_SMI (registers MON[4-7]_TRAP_EN and - MON[4-7]_TRAP_STS) - - page 407: TCO - register TCO1_CNT, bit NMI2SMI_EN, enables TCO to use SMI instead of NMI, - bit TCO_TMR_HLT, should be cleared to avoid being rebooted when the TCO - timer expires. Dangerous bit: TCO_LOCK locks the TCO timer until reboot. - register used by Linux drivers/char/watchdog/i8xx_tco.c - - page 492, 493: USB EHCI legacy support and SPECIAL SMI, i.e Intel Specific - USB 2.0 SMI register. - - page 520, SMBus - may be disabled by clearing register HOSTC, bit SMB_SMI_EN - register used by Linux driver drivers/i2c/busses/i2c-i801.c - -*/ _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git