From 4f14bdef41e599e218d71e3d0abf339d65e9b480 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 27 Mar 2008 23:37:58 +0100 Subject: x86: fix nmi_watchdog=2 on Pentium-D CPUs implement nmi_watchdog=2 on this class of CPUs: cpu family : 15 model : 6 model name : Intel(R) Pentium(R) D CPU 3.00GHz the watchdog's ->setup() method is safe anyway, so if the CPU cannot support it we'll bail out safely. Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perfctr-watchdog.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 9b838324b81..19a359472ae 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c @@ -652,9 +652,6 @@ static void probe_nmi_watchdog(void) wd_ops = &p6_wd_ops; break; case 15: - if (boot_cpu_data.x86_model > 0x4) - return; - wd_ops = &p4_wd_ops; break; default: -- cgit v1.2.3 From 9c9b81f77330ddc003a2de2f35fa6a20410c1a62 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 27 Mar 2008 23:39:42 +0100 Subject: x86: print message if nmi_watchdog=2 cannot be enabled right now if there's no CPU support for nmi_watchdog=2 we'll just refuse it silently. print a useful warning. Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perfctr-watchdog.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 19a359472ae..b943e10ad81 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c @@ -667,8 +667,10 @@ int lapic_watchdog_init(unsigned nmi_hz) { if (!wd_ops) { probe_nmi_watchdog(); - if (!wd_ops) + if (!wd_ops) { + printk(KERN_INFO "NMI watchdog: CPU not supported\n"); return -1; + } if (!wd_ops->reserve()) { printk(KERN_ERR -- cgit v1.2.3 From 8f59610de2fb244b5bc1a3feafd328a8d4d511d6 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 1 Apr 2008 14:24:03 +0200 Subject: x86, agpgart: scary messages are fortunately obsolete Fix obsolete printks in aperture-64. We used not to handle missing agpgart, but we handle it okay now. Signed-off-by: Pavel Machek Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-gart_64.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index faf3229f8fb..700e4647dd3 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -615,8 +615,8 @@ static __init int init_k8_gatt(struct agp_kern_info *info) nommu: /* Should not happen anymore */ - printk(KERN_ERR "PCI-DMA: More than 4GB of RAM and no IOMMU\n" - KERN_ERR "PCI-DMA: 32bit PCI IO may malfunction.\n"); + printk(KERN_WARNING "PCI-DMA: More than 4GB of RAM and no IOMMU\n" + KERN_WARNING "falling back to iommu=soft.\n"); return -1; } @@ -692,9 +692,9 @@ void __init gart_iommu_init(void) !gart_iommu_aperture || (no_agp && init_k8_gatt(&info) < 0)) { if (end_pfn > MAX_DMA32_PFN) { - printk(KERN_ERR "WARNING more than 4GB of memory " - "but GART IOMMU not available.\n" - KERN_ERR "WARNING 32bit PCI may malfunction.\n"); + printk(KERN_WARNING "More than 4GB of memory " + "but GART IOMMU not available.\n" + KERN_WARNING "falling back to iommu=soft.\n"); } return; } -- cgit v1.2.3 From f64337062c09c2c318fbcbf44ed1d739e8bc72ab Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Wed, 2 Apr 2008 15:36:36 +0100 Subject: xen: refactor xen_{alloc,release}_{pt,pd}() Signed-off-by: Mark McLoughlin Cc: xen-devel@lists.xensource.com Cc: Mark McLoughlin Cc: Jeremy Fitzhardinge Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 27 ++++++++++++++++++++------- arch/x86/xen/mmu.c | 7 ------- arch/x86/xen/mmu.h | 7 +++++++ 3 files changed, 27 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index de4e6f05840..16e2f8096a1 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -667,10 +667,10 @@ static void xen_release_pt_init(u32 pfn) make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); } -static void pin_pagetable_pfn(unsigned level, unsigned long pfn) +static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) { struct mmuext_op op; - op.cmd = level; + op.cmd = cmd; op.arg1.mfn = pfn_to_mfn(pfn); if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) BUG(); @@ -687,7 +687,10 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) if (!PageHighMem(page)) { make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); - pin_pagetable_pfn(level, pfn); + if (level == PT_PTE) + pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); + else if (level == PT_PMD) + pin_pagetable_pfn(MMUEXT_PIN_L2_TABLE, pfn); } else /* make sure there are no stray mappings of this page */ @@ -697,16 +700,16 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) static void xen_alloc_pt(struct mm_struct *mm, u32 pfn) { - xen_alloc_ptpage(mm, pfn, MMUEXT_PIN_L1_TABLE); + xen_alloc_ptpage(mm, pfn, PT_PTE); } static void xen_alloc_pd(struct mm_struct *mm, u32 pfn) { - xen_alloc_ptpage(mm, pfn, MMUEXT_PIN_L2_TABLE); + xen_alloc_ptpage(mm, pfn, PT_PMD); } /* This should never happen until we're OK to use struct page */ -static void xen_release_pt(u32 pfn) +static void xen_release_ptpage(u32 pfn, unsigned level) { struct page *page = pfn_to_page(pfn); @@ -718,6 +721,16 @@ static void xen_release_pt(u32 pfn) } } +static void xen_release_pt(u32 pfn) +{ + xen_release_ptpage(pfn, PT_PTE); +} + +static void xen_release_pd(u32 pfn) +{ + xen_release_ptpage(pfn, PT_PMD); +} + #ifdef CONFIG_HIGHPTE static void *xen_kmap_atomic_pte(struct page *page, enum km_type type) { @@ -838,7 +851,7 @@ static __init void xen_pagetable_setup_done(pgd_t *base) pv_mmu_ops.alloc_pt = xen_alloc_pt; pv_mmu_ops.alloc_pd = xen_alloc_pd; pv_mmu_ops.release_pt = xen_release_pt; - pv_mmu_ops.release_pd = xen_release_pt; + pv_mmu_ops.release_pd = xen_release_pd; pv_mmu_ops.set_pte = xen_set_pte; setup_shared_info(); diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 0144395448a..2a054ef2a3d 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -310,13 +310,6 @@ pgd_t xen_make_pgd(unsigned long pgd) } #endif /* CONFIG_X86_PAE */ -enum pt_level { - PT_PGD, - PT_PUD, - PT_PMD, - PT_PTE -}; - /* (Yet another) pagetable walker. This one is intended for pinning a pagetable. This means that it walks a pagetable and calls the diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h index c9ff27f3ac3..b5e189b1519 100644 --- a/arch/x86/xen/mmu.h +++ b/arch/x86/xen/mmu.h @@ -3,6 +3,13 @@ #include #include +enum pt_level { + PT_PGD, + PT_PUD, + PT_PMD, + PT_PTE +}; + /* * Page-directory addresses above 4GB do not fit into architectural %cr3. * When accessing %cr3, or equivalent field in vcpu_guest_context, guests -- cgit v1.2.3 From a684d69d15a8fafede7c5c0daac8c646bbee805c Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Wed, 2 Apr 2008 15:36:37 +0100 Subject: xen: Do not pin/unpin PMD pages i.e. with this simple test case: int fd = open("/dev/zero", O_RDONLY); munmap(mmap((void *)0x40000000, 0x1000_LEN, PROT_READ, MAP_PRIVATE, fd, 0), 0x1000); close(fd); we currently get: kernel BUG at arch/x86/xen/enlighten.c:678! ... EIP is at xen_release_pt+0x79/0xa9 ... Call Trace: [] ? __pmd_free_tlb+0x1a/0x75 [] ? free_pgd_range+0x1d2/0x2b5 [] ? free_pgtables+0x7e/0x93 [] ? unmap_region+0xb9/0xf5 [] ? do_munmap+0x193/0x1f5 [] ? sys_munmap+0x30/0x3f [] ? syscall_call+0x7/0xb ======================= and xen complains: (XEN) mm.c:2241:d4 Mfn 1cc37 not pinned Further details at: https://bugzilla.redhat.com/436453 Signed-off-by: Mark McLoughlin Cc: xen-devel@lists.xensource.com Cc: Mark McLoughlin Cc: Jeremy Fitzhardinge Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 16e2f8096a1..f16b056e5c5 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -689,8 +689,6 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); if (level == PT_PTE) pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); - else if (level == PT_PMD) - pin_pagetable_pfn(MMUEXT_PIN_L2_TABLE, pfn); } else /* make sure there are no stray mappings of this page */ @@ -715,7 +713,8 @@ static void xen_release_ptpage(u32 pfn, unsigned level) if (PagePinned(page)) { if (!PageHighMem(page)) { - pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); + if (level == PT_PTE) + pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); } } -- cgit v1.2.3 From c946c7de49a9ba50bc205d6359b41bbc8f01174c Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Wed, 2 Apr 2008 15:36:38 +0100 Subject: xen: Clear PG_pinned in release_{pt,pd}() Signed-off-by: Mark McLoughlin Cc: xen-devel@lists.xensource.com Cc: Mark McLoughlin Cc: Jeremy Fitzhardinge Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/xen/enlighten.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index f16b056e5c5..27ee26aedf9 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -717,6 +717,7 @@ static void xen_release_ptpage(u32 pfn, unsigned level) pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); } + ClearPagePinned(page); } } -- cgit v1.2.3 From 47001d603375f857a7fab0e9c095d964a1ea0039 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 1 Apr 2008 19:45:18 +0200 Subject: x86: tsc prevent time going backwards We already catch most of the TSC problems by sanity checks, but there is a subtle bug which has been in the code for ever. This can cause time jumps in the range of hours. This was reported in: http://lkml.org/lkml/2007/8/23/96 and http://lkml.org/lkml/2008/3/31/23 I was able to reproduce the problem with a gettimeofday loop test on a dual core and a quad core machine which both have sychronized TSCs. The TSCs seems not to be perfectly in sync though, but the kernel is not able to detect the slight delta in the sync check. Still there exists an extremly small window where this delta can be observed with a real big time jump. So far I was only able to reproduce this with the vsyscall gettimeofday implementation, but in theory this might be observable with the syscall based version as well. CPU 0 updates the clock source variables under xtime/vyscall lock and CPU1, where the TSC is slighty behind CPU0, is reading the time right after the seqlock was unlocked. The clocksource reference data was updated with the TSC from CPU0 and the value which is read from TSC on CPU1 is less than the reference data. This results in a huge delta value due to the unsigned subtraction of the TSC value and the reference value. This algorithm can not be changed due to the support of wrapping clock sources like pm timer. The huge delta is converted to nanoseconds and added to xtime, which is then observable by the caller. The next gettimeofday call on CPU1 will show the correct time again as now the TSC has advanced above the reference value. To prevent this TSC specific wreckage we need to compare the TSC value against the reference value and return the latter when it is larger than the actual TSC value. I pondered to mark the TSC unstable when the readout is smaller than the reference value, but this would render an otherwise good and fast clocksource unusable without a real good reason. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/tsc_32.c | 15 ++++++++++++++- arch/x86/kernel/tsc_64.c | 23 ++++++++++++++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c index f14cfd9d1f9..d7498b34c8e 100644 --- a/arch/x86/kernel/tsc_32.c +++ b/arch/x86/kernel/tsc_32.c @@ -287,14 +287,27 @@ core_initcall(cpufreq_tsc); /* clock source code */ static unsigned long current_tsc_khz = 0; +static struct clocksource clocksource_tsc; +/* + * We compare the TSC to the cycle_last value in the clocksource + * structure to avoid a nasty time-warp issue. This can be observed in + * a very small window right after one CPU updated cycle_last under + * xtime lock and the other CPU reads a TSC value which is smaller + * than the cycle_last reference value due to a TSC which is slighty + * behind. This delta is nowhere else observable, but in that case it + * results in a forward time jump in the range of hours due to the + * unsigned delta calculation of the time keeping core code, which is + * necessary to support wrapping clocksources like pm timer. + */ static cycle_t read_tsc(void) { cycle_t ret; rdtscll(ret); - return ret; + return ret >= clocksource_tsc.cycle_last ? + ret : clocksource_tsc.cycle_last; } static struct clocksource clocksource_tsc = { diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c index 947554ddabb..01fc9f0c39e 100644 --- a/arch/x86/kernel/tsc_64.c +++ b/arch/x86/kernel/tsc_64.c @@ -11,6 +11,7 @@ #include #include #include +#include static int notsc __initdata = 0; @@ -290,18 +291,34 @@ int __init notsc_setup(char *s) __setup("notsc", notsc_setup); +static struct clocksource clocksource_tsc; -/* clock source code: */ +/* + * We compare the TSC to the cycle_last value in the clocksource + * structure to avoid a nasty time-warp. This can be observed in a + * very small window right after one CPU updated cycle_last under + * xtime/vsyscall_gtod lock and the other CPU reads a TSC value which + * is smaller than the cycle_last reference value due to a TSC which + * is slighty behind. This delta is nowhere else observable, but in + * that case it results in a forward time jump in the range of hours + * due to the unsigned delta calculation of the time keeping core + * code, which is necessary to support wrapping clocksources like pm + * timer. + */ static cycle_t read_tsc(void) { cycle_t ret = (cycle_t)get_cycles(); - return ret; + + return ret >= clocksource_tsc.cycle_last ? + ret : clocksource_tsc.cycle_last; } static cycle_t __vsyscall_fn vread_tsc(void) { cycle_t ret = (cycle_t)vget_cycles(); - return ret; + + return ret >= __vsyscall_gtod_data.clock.cycle_last ? + ret : __vsyscall_gtod_data.clock.cycle_last; } static struct clocksource clocksource_tsc = { -- cgit v1.2.3 From 5761d64b277c287a7520b868c32d656ef03374b4 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 4 Apr 2008 16:26:10 +0200 Subject: x86: revert assign IRQs to hpet timer The commits: commit 37a47db8d7f0f38dac5acf5a13abbc8f401707fa Author: Balaji Rao Date: Wed Jan 30 13:30:03 2008 +0100 x86: assign IRQs to HPET timers, fix and commit e3f37a54f690d3e64995ea7ecea08c5ab3070faf Author: Balaji Rao Date: Wed Jan 30 13:30:03 2008 +0100 x86: assign IRQs to HPET timers have been identified to cause a regression on some platforms due to the assignement of legacy IRQs which makes the legacy devices connected to those IRQs disfunctional. Revert them. This fixes http://bugzilla.kernel.org/show_bug.cgi?id=10382 Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar --- arch/x86/kernel/hpet.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 235fd6c7750..36652ea1a26 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -133,13 +133,16 @@ static void hpet_reserve_platform_timers(unsigned long id) #ifdef CONFIG_HPET_EMULATE_RTC hpet_reserve_timer(&hd, 1); #endif + hd.hd_irq[0] = HPET_LEGACY_8254; hd.hd_irq[1] = HPET_LEGACY_RTC; - for (i = 2; i < nrtimers; timer++, i++) - hd.hd_irq[i] = (timer->hpet_config & Tn_INT_ROUTE_CNF_MASK) >> - Tn_INT_ROUTE_CNF_SHIFT; + for (i = 2; i < nrtimers; timer++, i++) + hd.hd_irq[i] = (timer->hpet_config & Tn_INT_ROUTE_CNF_MASK) >> + Tn_INT_ROUTE_CNF_SHIFT; + hpet_alloc(&hd); + } #else static void hpet_reserve_platform_timers(unsigned long id) { } -- cgit v1.2.3