From: Holger Steinhaus Subject: [PATCH] force HPET support on buggy NVidia-based machines Date: Fri, 25 Jan 2008 11:02:33 +0100 Message-ID: <200801251102.33727.hsteinhaus@gmx.de> Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_5ObmHCN6g0580J9" Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org --Boundary-00=_5ObmHCN6g0580J9 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline While playing around with some cpufreq issues, I found out that Xen unstable is currently unable to use the HPET timer of my NVidia Nforce Pro-based machine. Some research on the net revealed that quite a lot dual socket machines (i.e. workstations and small servers from Dell and HP) don't provide correct ACPI information about this timer, even though the HPET is present and functional. Very recent Linux kernels (starting from 2.6.23(?)) as well as LinuxBIOS therefore provide a workaround to enable the HPET anyway by scanning the PCI bus for suspicious devices and querying them directly. I've ported a part of this workaround to Xen. To enable it, apply the patch below and pass the cmd line arg "clocksource=hpet_nv" to Xen. This patch currently only covers some NVidia chipsets with the PCI ids shown in the patch.Other chipsets may need a similar procedure. The original Linux source even covers Intel (ICH4) and VIA chipsets. The patch below has been tested on my Tyan K8SE mainboard using a NForce Pro 2200 chipset and does it's job without woes so far. I'm not sure if patches like this one are really a good idea for Xen, but maybe it helps some other people to run Xen more smoothly on their development machines. Regards, Holger Signed-off-by: Holger Steinhaus --Boundary-00=_5ObmHCN6g0580J9 Content-Type: text/x-diff; charset="utf-8"; name="xen-3.3-unstable-hpet-force.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="xen-3.3-unstable-hpet-force.diff" diff -r bf828db8d017 xen/arch/x86/time.c --- a/xen/arch/x86/time.c Thu Jan 17 16:39:14 2008 +0000 +++ b/xen/arch/x86/time.c Sat Jan 19 23:51:24 2008 +0100 @@ -320,6 +320,130 @@ static u32 read_hpet_count(void) return hpet_read32(HPET_COUNTER); } +#define PDprintk(x...) + +static inline u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset) +{ + u32 v; + outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); + v = inl(0xcfc); + if (v != 0xffffffff) + PDprintk("%x reading 4 from %x: %x\n", slot, offset, v); + return v; +} + +static inline u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset) +{ + u8 v; + outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); + v = inb(0xcfc + (offset&3)); + PDprintk("%x reading 1 from %x: %x\n", slot, offset, v); + return v; +} + + +static void detect_nforce_hpet(int num, int slot, int func) +{ + u32 addr; + + addr = read_pci_config(num, slot, func, 0x44); + if (!addr) { + return; + } + + hpet_address = addr; + printk(KERN_INFO "NVidia quirk. Enabled hidden HPET that BIOS had " + "configured at base: %#x\n", addr); +} + +struct pci_entry { + u16 class; + u16 vendor; + u16 device; + void (*f)(int num, int slot, int func); +}; + +#define PCI_HEADER_TYPE 0x0e +#define PCI_VENDOR_ID 0x00 +#define PCI_CLASS_REVISION 0x08 +#define PCI_CLASS_BRIDGE_ISA 0x0601 +#define PCI_VENDOR_ID_NVIDIA 0x10de + + +static struct pci_entry nforce_hpet_chips[] __initdata = { + { PCI_CLASS_BRIDGE_ISA, PCI_VENDOR_ID_NVIDIA, 0x0050, detect_nforce_hpet }, + { PCI_CLASS_BRIDGE_ISA, PCI_VENDOR_ID_NVIDIA, 0x0051, detect_nforce_hpet }, + { PCI_CLASS_BRIDGE_ISA, PCI_VENDOR_ID_NVIDIA, 0x0360, detect_nforce_hpet }, + { PCI_CLASS_BRIDGE_ISA, PCI_VENDOR_ID_NVIDIA, 0x0361, detect_nforce_hpet }, + { PCI_CLASS_BRIDGE_ISA, PCI_VENDOR_ID_NVIDIA, 0x0362, detect_nforce_hpet }, + { PCI_CLASS_BRIDGE_ISA, PCI_VENDOR_ID_NVIDIA, 0x0363, detect_nforce_hpet }, + { PCI_CLASS_BRIDGE_ISA, PCI_VENDOR_ID_NVIDIA, 0x0364, detect_nforce_hpet }, + { PCI_CLASS_BRIDGE_ISA, PCI_VENDOR_ID_NVIDIA, 0x0365, detect_nforce_hpet }, + { PCI_CLASS_BRIDGE_ISA, PCI_VENDOR_ID_NVIDIA, 0x0366, detect_nforce_hpet }, + { PCI_CLASS_BRIDGE_ISA, PCI_VENDOR_ID_NVIDIA, 0x0367, detect_nforce_hpet }, + {} +}; + + +void early_pci_scan(struct pci_entry matching[]) +{ + int num, slot, func; + + /* Poor man's PCI discovery */ + for (num = 0; num < 32; num++) { + for (slot = 0; slot < 32; slot++) { + for (func = 0; func < 8; func++) { + u32 class; + u32 vendor; + u8 type; + int i; + class = read_pci_config(num,slot,func, + PCI_CLASS_REVISION); + if (class == 0xffffffff) + break; + + class >>= 16; + + vendor = read_pci_config(num, slot, func, + PCI_VENDOR_ID); + + for (i = 0; matching[i].f; i++) { + if (class != matching[i].class) + continue; + + if ((vendor & 0xffff) != matching[i].vendor) + continue; + + if (matching[i].device != 0xffff && + (vendor >> 16) != matching[i].device) + continue; + + matching[i].f(num, slot, func); + return; + } + + /* No multi-function device? */ + type = read_pci_config_byte(num,slot,func, + PCI_HEADER_TYPE); + if (!(type & 0x80)) + break; + } + } + } +} + +static int enable_nvidia_hpet(void) +{ + if (hpet_address) + return 0; + + early_pci_scan(nforce_hpet_chips); + + return hpet_address != 0; +} + + + static int init_hpet(struct platform_timesource *pts) { u64 hpet_rate; @@ -540,6 +664,11 @@ static void init_platform_timer(void) rc = (init_pit(pts), 1); else if ( !strcmp(opt_clocksource, "hpet") ) rc = init_hpet(pts); + else if ( !strcmp(opt_clocksource, "hpet_nv") ) + { + enable_nvidia_hpet(); + rc = init_hpet(pts); + } else if ( !strcmp(opt_clocksource, "cyclone") ) rc = init_cyclone(pts); else if ( !strcmp(opt_clocksource, "acpi") ) --Boundary-00=_5ObmHCN6g0580J9 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --Boundary-00=_5ObmHCN6g0580J9--