Skip to content

Commit c00193f

Browse files
author
Ingo Molnar
committed
Merge branches 'oprofile-v2' and 'timers/hpet' into x86/core-v4
3 parents c1a2f4b + accba5f + f26ed11 commit c00193f

File tree

20 files changed

+1004
-374
lines changed

20 files changed

+1004
-374
lines changed

Documentation/00-INDEX

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,6 @@ hayes-esp.txt
159159
- info on using the Hayes ESP serial driver.
160160
highuid.txt
161161
- notes on the change from 16 bit to 32 bit user/group IDs.
162-
hpet.txt
163-
- High Precision Event Timer Driver for Linux.
164162
timers/
165163
- info on the timer related topics
166164
hw_random.txt

Documentation/timers/00-INDEX

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
00-INDEX
2+
- this file
3+
highres.txt
4+
- High resolution timers and dynamic ticks design notes
5+
hpet.txt
6+
- High Precision Event Timer Driver for Linux
7+
hrtimers.txt
8+
- subsystem for high-resolution kernel timers
9+
timer_stats.txt
10+
- timer usage statistics

Documentation/hpet.txt renamed to Documentation/timers/hpet.txt

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,32 @@
11
High Precision Event Timer Driver for Linux
22

3-
The High Precision Event Timer (HPET) hardware is the future replacement
4-
for the 8254 and Real Time Clock (RTC) periodic timer functionality.
5-
Each HPET can have up to 32 timers. It is possible to configure the
6-
first two timers as legacy replacements for 8254 and RTC periodic timers.
7-
A specification done by Intel and Microsoft can be found at
8-
<http://www.intel.com/technology/architecture/hpetspec.htm>.
3+
The High Precision Event Timer (HPET) hardware follows a specification
4+
by Intel and Microsoft which can be found at
5+
6+
http://www.intel.com/technology/architecture/hpetspec.htm
7+
8+
Each HPET has one fixed-rate counter (at 10+ MHz, hence "High Precision")
9+
and up to 32 comparators. Normally three or more comparators are provided,
10+
each of which can generate oneshot interupts and at least one of which has
11+
additional hardware to support periodic interrupts. The comparators are
12+
also called "timers", which can be misleading since usually timers are
13+
independent of each other ... these share a counter, complicating resets.
14+
15+
HPET devices can support two interrupt routing modes. In one mode, the
16+
comparators are additional interrupt sources with no particular system
17+
role. Many x86 BIOS writers don't route HPET interrupts at all, which
18+
prevents use of that mode. They support the other "legacy replacement"
19+
mode where the first two comparators block interrupts from 8254 timers
20+
and from the RTC.
921

1022
The driver supports detection of HPET driver allocation and initialization
1123
of the HPET before the driver module_init routine is called. This enables
1224
platform code which uses timer 0 or 1 as the main timer to intercept HPET
1325
initialization. An example of this initialization can be found in
14-
arch/i386/kernel/time_hpet.c.
26+
arch/x86/kernel/hpet.c.
1527

16-
The driver provides two APIs which are very similar to the API found in
17-
the rtc.c driver. There is a user space API and a kernel space API.
18-
An example user space program is provided below.
28+
The driver provides a userspace API which resembles the API found in the
29+
RTC driver framework. An example user space program is provided below.
1930

2031
#include <stdio.h>
2132
#include <stdlib.h>
@@ -286,15 +297,3 @@ out:
286297

287298
return;
288299
}
289-
290-
The kernel API has three interfaces exported from the driver:
291-
292-
hpet_register(struct hpet_task *tp, int periodic)
293-
hpet_unregister(struct hpet_task *tp)
294-
hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
295-
296-
The kernel module using this interface fills in the ht_func and ht_data
297-
members of the hpet_task structure before calling hpet_register.
298-
hpet_control simply vectors to the hpet_ioctl routine and has the same
299-
commands and respective arguments as the user API. hpet_unregister
300-
is used to terminate usage of the HPET timer reserved by hpet_register.

arch/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@ config OPROFILE
1313

1414
If unsure, say N.
1515

16+
config OPROFILE_IBS
17+
bool "OProfile AMD IBS support (EXPERIMENTAL)"
18+
default n
19+
depends on OPROFILE && SMP && X86
20+
help
21+
Instruction-Based Sampling (IBS) is a new profiling
22+
technique that provides rich, precise program performance
23+
information. IBS is introduced by AMD Family10h processors
24+
(AMD Opteron Quad-Core processor “Barcelona”) to overcome
25+
the limitations of conventional performance counter
26+
sampling.
27+
28+
If unsure, say N.
29+
1630
config HAVE_OPROFILE
1731
def_bool n
1832

arch/x86/kernel/apic_32.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
295295
*
296296
* Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
297297
* MCE interrupts are supported. Thus MCE offset must be set to 0.
298+
*
299+
* If mask=1, the LVT entry does not generate interrupts while mask=0
300+
* enables the vector. See also the BKDGs.
298301
*/
299302

300303
#define APIC_EILVT_LVTOFF_MCE 0
@@ -319,6 +322,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
319322
setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask);
320323
return APIC_EILVT_LVTOFF_IBS;
321324
}
325+
EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs);
322326

323327
/*
324328
* Program the next event, relative to now

arch/x86/kernel/apic_64.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
307307
*
308308
* Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
309309
* MCE interrupts are supported. Thus MCE offset must be set to 0.
310+
*
311+
* If mask=1, the LVT entry does not generate interrupts while mask=0
312+
* enables the vector. See also the BKDGs.
310313
*/
311314

312315
#define APIC_EILVT_LVTOFF_MCE 0
@@ -331,6 +334,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
331334
setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask);
332335
return APIC_EILVT_LVTOFF_IBS;
333336
}
337+
EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs);
334338

335339
/*
336340
* Program the next event, relative to now

arch/x86/kernel/hpet.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,17 @@ static void hpet_reserve_platform_timers(unsigned long id)
115115
hd.hd_phys_address = hpet_address;
116116
hd.hd_address = hpet;
117117
hd.hd_nirqs = nrtimers;
118-
hd.hd_flags = HPET_DATA_PLATFORM;
119118
hpet_reserve_timer(&hd, 0);
120119

121120
#ifdef CONFIG_HPET_EMULATE_RTC
122121
hpet_reserve_timer(&hd, 1);
123122
#endif
124123

124+
/*
125+
* NOTE that hd_irq[] reflects IOAPIC input pins (LEGACY_8254
126+
* is wrong for i8259!) not the output IRQ. Many BIOS writers
127+
* don't bother configuring *any* comparator interrupts.
128+
*/
125129
hd.hd_irq[0] = HPET_LEGACY_8254;
126130
hd.hd_irq[1] = HPET_LEGACY_RTC;
127131

arch/x86/kernel/quirks.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,27 @@ static void ati_force_hpet_resume(void)
354354
printk(KERN_DEBUG "Force enabled HPET at resume\n");
355355
}
356356

357+
static u32 ati_ixp4x0_rev(struct pci_dev *dev)
358+
{
359+
u32 d;
360+
u8 b;
361+
362+
pci_read_config_byte(dev, 0xac, &b);
363+
b &= ~(1<<5);
364+
pci_write_config_byte(dev, 0xac, b);
365+
pci_read_config_dword(dev, 0x70, &d);
366+
d |= 1<<8;
367+
pci_write_config_dword(dev, 0x70, d);
368+
pci_read_config_dword(dev, 0x8, &d);
369+
d &= 0xff;
370+
dev_printk(KERN_DEBUG, &dev->dev, "SB4X0 revision 0x%x\n", d);
371+
return d;
372+
}
373+
357374
static void ati_force_enable_hpet(struct pci_dev *dev)
358375
{
359-
u32 uninitialized_var(val);
376+
u32 d, val;
377+
u8 b;
360378

361379
if (hpet_address || force_hpet_address)
362380
return;
@@ -366,14 +384,33 @@ static void ati_force_enable_hpet(struct pci_dev *dev)
366384
return;
367385
}
368386

387+
d = ati_ixp4x0_rev(dev);
388+
if (d < 0x82)
389+
return;
390+
391+
/* base address */
369392
pci_write_config_dword(dev, 0x14, 0xfed00000);
370393
pci_read_config_dword(dev, 0x14, &val);
394+
395+
/* enable interrupt */
396+
outb(0x72, 0xcd6); b = inb(0xcd7);
397+
b |= 0x1;
398+
outb(0x72, 0xcd6); outb(b, 0xcd7);
399+
outb(0x72, 0xcd6); b = inb(0xcd7);
400+
if (!(b & 0x1))
401+
return;
402+
pci_read_config_dword(dev, 0x64, &d);
403+
d |= (1<<10);
404+
pci_write_config_dword(dev, 0x64, d);
405+
pci_read_config_dword(dev, 0x64, &d);
406+
if (!(d & (1<<10)))
407+
return;
408+
371409
force_hpet_address = val;
372410
force_hpet_resume_type = ATI_FORCE_HPET_RESUME;
373411
dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
374412
force_hpet_address);
375413
cached_dev = dev;
376-
return;
377414
}
378415
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS,
379416
ati_force_enable_hpet);

arch/x86/oprofile/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
77
timer_int.o )
88

99
oprofile-y := $(DRIVER_OBJS) init.o backtrace.o
10-
oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \
10+
oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_amd.o \
1111
op_model_ppro.o op_model_p4.o
1212
oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o

arch/x86/oprofile/nmi_int.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
/**
22
* @file nmi_int.c
33
*
4-
* @remark Copyright 2002 OProfile authors
4+
* @remark Copyright 2002-2008 OProfile authors
55
* @remark Read the file COPYING
66
*
77
* @author John Levon <[email protected]>
8+
* @author Robert Richter <[email protected]>
89
*/
910

1011
#include <linux/init.h>
@@ -439,6 +440,7 @@ int __init op_nmi_init(struct oprofile_operations *ops)
439440
__u8 vendor = boot_cpu_data.x86_vendor;
440441
__u8 family = boot_cpu_data.x86;
441442
char *cpu_type;
443+
int ret = 0;
442444

443445
if (!cpu_has_apic)
444446
return -ENODEV;
@@ -451,19 +453,23 @@ int __init op_nmi_init(struct oprofile_operations *ops)
451453
default:
452454
return -ENODEV;
453455
case 6:
454-
model = &op_athlon_spec;
456+
model = &op_amd_spec;
455457
cpu_type = "i386/athlon";
456458
break;
457459
case 0xf:
458-
model = &op_athlon_spec;
460+
model = &op_amd_spec;
459461
/* Actually it could be i386/hammer too, but give
460462
user space an consistent name. */
461463
cpu_type = "x86-64/hammer";
462464
break;
463465
case 0x10:
464-
model = &op_athlon_spec;
466+
model = &op_amd_spec;
465467
cpu_type = "x86-64/family10";
466468
break;
469+
case 0x11:
470+
model = &op_amd_spec;
471+
cpu_type = "x86-64/family11h";
472+
break;
467473
}
468474
break;
469475

@@ -490,17 +496,24 @@ int __init op_nmi_init(struct oprofile_operations *ops)
490496
return -ENODEV;
491497
}
492498

493-
init_sysfs();
494499
#ifdef CONFIG_SMP
495500
register_cpu_notifier(&oprofile_cpu_nb);
496501
#endif
497-
using_nmi = 1;
502+
/* default values, can be overwritten by model */
498503
ops->create_files = nmi_create_files;
499504
ops->setup = nmi_setup;
500505
ops->shutdown = nmi_shutdown;
501506
ops->start = nmi_start;
502507
ops->stop = nmi_stop;
503508
ops->cpu_type = cpu_type;
509+
510+
if (model->init)
511+
ret = model->init(ops);
512+
if (ret)
513+
return ret;
514+
515+
init_sysfs();
516+
using_nmi = 1;
504517
printk(KERN_INFO "oprofile: using NMI interrupt.\n");
505518
return 0;
506519
}
@@ -513,4 +526,6 @@ void op_nmi_exit(void)
513526
unregister_cpu_notifier(&oprofile_cpu_nb);
514527
#endif
515528
}
529+
if (model->exit)
530+
model->exit();
516531
}

0 commit comments

Comments
 (0)