Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
c00193f9
Commit
c00193f9
authored
Oct 13, 2008
by
Ingo Molnar
Browse files
Options
Browse Files
Download
Plain Diff
Merge branches 'oprofile-v2' and 'timers/hpet' into x86/core-v4
parents
c1a2f4b1
accba5f3
f26ed116
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1004 additions
and
184 deletions
+1004
-184
Documentation/00-INDEX
Documentation/00-INDEX
+0
-2
Documentation/timers/00-INDEX
Documentation/timers/00-INDEX
+10
-0
Documentation/timers/hpet.txt
Documentation/timers/hpet.txt
+21
-22
arch/Kconfig
arch/Kconfig
+14
-0
arch/x86/kernel/apic_32.c
arch/x86/kernel/apic_32.c
+4
-0
arch/x86/kernel/apic_64.c
arch/x86/kernel/apic_64.c
+4
-0
arch/x86/kernel/hpet.c
arch/x86/kernel/hpet.c
+5
-1
arch/x86/kernel/quirks.c
arch/x86/kernel/quirks.c
+39
-2
arch/x86/oprofile/Makefile
arch/x86/oprofile/Makefile
+1
-1
arch/x86/oprofile/nmi_int.c
arch/x86/oprofile/nmi_int.c
+21
-6
arch/x86/oprofile/op_model_amd.c
arch/x86/oprofile/op_model_amd.c
+543
-0
arch/x86/oprofile/op_x86_model.h
arch/x86/oprofile/op_x86_model.h
+3
-1
arch/x86/pci/fixup.c
arch/x86/pci/fixup.c
+28
-0
drivers/char/hpet.c
drivers/char/hpet.c
+89
-70
drivers/oprofile/buffer_sync.c
drivers/oprofile/buffer_sync.c
+143
-66
drivers/oprofile/cpu_buffer.c
drivers/oprofile/cpu_buffer.c
+72
-2
drivers/oprofile/cpu_buffer.h
drivers/oprofile/cpu_buffer.h
+2
-0
include/linux/hpet.h
include/linux/hpet.h
+3
-11
include/linux/oprofile.h
include/linux/oprofile.h
+2
-0
No files found.
Documentation/00-INDEX
View file @
c00193f9
...
...
@@ -159,8 +159,6 @@ hayes-esp.txt
- info on using the Hayes ESP serial driver.
highuid.txt
- notes on the change from 16 bit to 32 bit user/group IDs.
hpet.txt
- High Precision Event Timer Driver for Linux.
timers/
- info on the timer related topics
hw_random.txt
...
...
Documentation/timers/00-INDEX
0 → 100644
View file @
c00193f9
00-INDEX
- this file
highres.txt
- High resolution timers and dynamic ticks design notes
hpet.txt
- High Precision Event Timer Driver for Linux
hrtimers.txt
- subsystem for high-resolution kernel timers
timer_stats.txt
- timer usage statistics
Documentation/hpet.txt
→
Documentation/
timers/
hpet.txt
View file @
c00193f9
High Precision Event Timer Driver for Linux
The High Precision Event Timer (HPET) hardware is the future replacement
for the 8254 and Real Time Clock (RTC) periodic timer functionality.
Each HPET can have up to 32 timers. It is possible to configure the
first two timers as legacy replacements for 8254 and RTC periodic timers.
A specification done by Intel and Microsoft can be found at
<http://www.intel.com/technology/architecture/hpetspec.htm>.
The High Precision Event Timer (HPET) hardware follows a specification
by Intel and Microsoft which can be found at
http://www.intel.com/technology/architecture/hpetspec.htm
Each HPET has one fixed-rate counter (at 10+ MHz, hence "High Precision")
and up to 32 comparators. Normally three or more comparators are provided,
each of which can generate oneshot interupts and at least one of which has
additional hardware to support periodic interrupts. The comparators are
also called "timers", which can be misleading since usually timers are
independent of each other ... these share a counter, complicating resets.
HPET devices can support two interrupt routing modes. In one mode, the
comparators are additional interrupt sources with no particular system
role. Many x86 BIOS writers don't route HPET interrupts at all, which
prevents use of that mode. They support the other "legacy replacement"
mode where the first two comparators block interrupts from 8254 timers
and from the RTC.
The driver supports detection of HPET driver allocation and initialization
of the HPET before the driver module_init routine is called. This enables
platform code which uses timer 0 or 1 as the main timer to intercept HPET
initialization. An example of this initialization can be found in
arch/
i386/kernel/time_
hpet.c.
arch/
x86/kernel/
hpet.c.
The driver provides two APIs which are very similar to the API found in
the rtc.c driver. There is a user space API and a kernel space API.
An example user space program is provided below.
The driver provides a userspace API which resembles the API found in the
RTC driver framework. An example user space program is provided below.
#include <stdio.h>
#include <stdlib.h>
...
...
@@ -286,15 +297,3 @@ out:
return;
}
The kernel API has three interfaces exported from the driver:
hpet_register(struct hpet_task *tp, int periodic)
hpet_unregister(struct hpet_task *tp)
hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
The kernel module using this interface fills in the ht_func and ht_data
members of the hpet_task structure before calling hpet_register.
hpet_control simply vectors to the hpet_ioctl routine and has the same
commands and respective arguments as the user API. hpet_unregister
is used to terminate usage of the HPET timer reserved by hpet_register.
arch/Kconfig
View file @
c00193f9
...
...
@@ -13,6 +13,20 @@ config OPROFILE
If unsure, say N.
config OPROFILE_IBS
bool "OProfile AMD IBS support (EXPERIMENTAL)"
default n
depends on OPROFILE && SMP && X86
help
Instruction-Based Sampling (IBS) is a new profiling
technique that provides rich, precise program performance
information. IBS is introduced by AMD Family10h processors
(AMD Opteron Quad-Core processor “Barcelona”) to overcome
the limitations of conventional performance counter
sampling.
If unsure, say N.
config HAVE_OPROFILE
def_bool n
...
...
arch/x86/kernel/apic_32.c
View file @
c00193f9
...
...
@@ -295,6 +295,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
*
* Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
* MCE interrupts are supported. Thus MCE offset must be set to 0.
*
* If mask=1, the LVT entry does not generate interrupts while mask=0
* enables the vector. See also the BKDGs.
*/
#define APIC_EILVT_LVTOFF_MCE 0
...
...
@@ -319,6 +322,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
setup_APIC_eilvt
(
APIC_EILVT_LVTOFF_IBS
,
vector
,
msg_type
,
mask
);
return
APIC_EILVT_LVTOFF_IBS
;
}
EXPORT_SYMBOL_GPL
(
setup_APIC_eilvt_ibs
);
/*
* Program the next event, relative to now
...
...
arch/x86/kernel/apic_64.c
View file @
c00193f9
...
...
@@ -307,6 +307,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
*
* Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
* MCE interrupts are supported. Thus MCE offset must be set to 0.
*
* If mask=1, the LVT entry does not generate interrupts while mask=0
* enables the vector. See also the BKDGs.
*/
#define APIC_EILVT_LVTOFF_MCE 0
...
...
@@ -331,6 +334,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
setup_APIC_eilvt
(
APIC_EILVT_LVTOFF_IBS
,
vector
,
msg_type
,
mask
);
return
APIC_EILVT_LVTOFF_IBS
;
}
EXPORT_SYMBOL_GPL
(
setup_APIC_eilvt_ibs
);
/*
* Program the next event, relative to now
...
...
arch/x86/kernel/hpet.c
View file @
c00193f9
...
...
@@ -115,13 +115,17 @@ static void hpet_reserve_platform_timers(unsigned long id)
hd
.
hd_phys_address
=
hpet_address
;
hd
.
hd_address
=
hpet
;
hd
.
hd_nirqs
=
nrtimers
;
hd
.
hd_flags
=
HPET_DATA_PLATFORM
;
hpet_reserve_timer
(
&
hd
,
0
);
#ifdef CONFIG_HPET_EMULATE_RTC
hpet_reserve_timer
(
&
hd
,
1
);
#endif
/*
* NOTE that hd_irq[] reflects IOAPIC input pins (LEGACY_8254
* is wrong for i8259!) not the output IRQ. Many BIOS writers
* don't bother configuring *any* comparator interrupts.
*/
hd
.
hd_irq
[
0
]
=
HPET_LEGACY_8254
;
hd
.
hd_irq
[
1
]
=
HPET_LEGACY_RTC
;
...
...
arch/x86/kernel/quirks.c
View file @
c00193f9
...
...
@@ -354,9 +354,27 @@ static void ati_force_hpet_resume(void)
printk
(
KERN_DEBUG
"Force enabled HPET at resume
\n
"
);
}
static
u32
ati_ixp4x0_rev
(
struct
pci_dev
*
dev
)
{
u32
d
;
u8
b
;
pci_read_config_byte
(
dev
,
0xac
,
&
b
);
b
&=
~
(
1
<<
5
);
pci_write_config_byte
(
dev
,
0xac
,
b
);
pci_read_config_dword
(
dev
,
0x70
,
&
d
);
d
|=
1
<<
8
;
pci_write_config_dword
(
dev
,
0x70
,
d
);
pci_read_config_dword
(
dev
,
0x8
,
&
d
);
d
&=
0xff
;
dev_printk
(
KERN_DEBUG
,
&
dev
->
dev
,
"SB4X0 revision 0x%x
\n
"
,
d
);
return
d
;
}
static
void
ati_force_enable_hpet
(
struct
pci_dev
*
dev
)
{
u32
uninitialized_var
(
val
);
u32
d
,
val
;
u8
b
;
if
(
hpet_address
||
force_hpet_address
)
return
;
...
...
@@ -366,14 +384,33 @@ static void ati_force_enable_hpet(struct pci_dev *dev)
return
;
}
d
=
ati_ixp4x0_rev
(
dev
);
if
(
d
<
0x82
)
return
;
/* base address */
pci_write_config_dword
(
dev
,
0x14
,
0xfed00000
);
pci_read_config_dword
(
dev
,
0x14
,
&
val
);
/* enable interrupt */
outb
(
0x72
,
0xcd6
);
b
=
inb
(
0xcd7
);
b
|=
0x1
;
outb
(
0x72
,
0xcd6
);
outb
(
b
,
0xcd7
);
outb
(
0x72
,
0xcd6
);
b
=
inb
(
0xcd7
);
if
(
!
(
b
&
0x1
))
return
;
pci_read_config_dword
(
dev
,
0x64
,
&
d
);
d
|=
(
1
<<
10
);
pci_write_config_dword
(
dev
,
0x64
,
d
);
pci_read_config_dword
(
dev
,
0x64
,
&
d
);
if
(
!
(
d
&
(
1
<<
10
)))
return
;
force_hpet_address
=
val
;
force_hpet_resume_type
=
ATI_FORCE_HPET_RESUME
;
dev_printk
(
KERN_DEBUG
,
&
dev
->
dev
,
"Force enabled HPET at 0x%lx
\n
"
,
force_hpet_address
);
cached_dev
=
dev
;
return
;
}
DECLARE_PCI_FIXUP_HEADER
(
PCI_VENDOR_ID_ATI
,
PCI_DEVICE_ID_ATI_IXP400_SMBUS
,
ati_force_enable_hpet
);
...
...
arch/x86/oprofile/Makefile
View file @
c00193f9
...
...
@@ -7,6 +7,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
timer_int.o
)
oprofile-y
:=
$(DRIVER_OBJS)
init.o backtrace.o
oprofile-$(CONFIG_X86_LOCAL_APIC)
+=
nmi_int.o op_model_a
thlon
.o
\
oprofile-$(CONFIG_X86_LOCAL_APIC)
+=
nmi_int.o op_model_a
md
.o
\
op_model_ppro.o op_model_p4.o
oprofile-$(CONFIG_X86_IO_APIC)
+=
nmi_timer_int.o
arch/x86/oprofile/nmi_int.c
View file @
c00193f9
/**
* @file nmi_int.c
*
* @remark Copyright 2002 OProfile authors
* @remark Copyright 2002
-2008
OProfile authors
* @remark Read the file COPYING
*
* @author John Levon <levon@movementarian.org>
* @author Robert Richter <robert.richter@amd.com>
*/
#include <linux/init.h>
...
...
@@ -439,6 +440,7 @@ int __init op_nmi_init(struct oprofile_operations *ops)
__u8
vendor
=
boot_cpu_data
.
x86_vendor
;
__u8
family
=
boot_cpu_data
.
x86
;
char
*
cpu_type
;
int
ret
=
0
;
if
(
!
cpu_has_apic
)
return
-
ENODEV
;
...
...
@@ -451,19 +453,23 @@ int __init op_nmi_init(struct oprofile_operations *ops)
default:
return
-
ENODEV
;
case
6
:
model
=
&
op_a
thlon
_spec
;
model
=
&
op_a
md
_spec
;
cpu_type
=
"i386/athlon"
;
break
;
case
0xf
:
model
=
&
op_a
thlon
_spec
;
model
=
&
op_a
md
_spec
;
/* Actually it could be i386/hammer too, but give
user space an consistent name. */
cpu_type
=
"x86-64/hammer"
;
break
;
case
0x10
:
model
=
&
op_a
thlon
_spec
;
model
=
&
op_a
md
_spec
;
cpu_type
=
"x86-64/family10"
;
break
;
case
0x11
:
model
=
&
op_amd_spec
;
cpu_type
=
"x86-64/family11h"
;
break
;
}
break
;
...
...
@@ -490,17 +496,24 @@ int __init op_nmi_init(struct oprofile_operations *ops)
return
-
ENODEV
;
}
init_sysfs
();
#ifdef CONFIG_SMP
register_cpu_notifier
(
&
oprofile_cpu_nb
);
#endif
using_nmi
=
1
;
/* default values, can be overwritten by model */
ops
->
create_files
=
nmi_create_files
;
ops
->
setup
=
nmi_setup
;
ops
->
shutdown
=
nmi_shutdown
;
ops
->
start
=
nmi_start
;
ops
->
stop
=
nmi_stop
;
ops
->
cpu_type
=
cpu_type
;
if
(
model
->
init
)
ret
=
model
->
init
(
ops
);
if
(
ret
)
return
ret
;
init_sysfs
();
using_nmi
=
1
;
printk
(
KERN_INFO
"oprofile: using NMI interrupt.
\n
"
);
return
0
;
}
...
...
@@ -513,4 +526,6 @@ void op_nmi_exit(void)
unregister_cpu_notifier
(
&
oprofile_cpu_nb
);
#endif
}
if
(
model
->
exit
)
model
->
exit
();
}
arch/x86/oprofile/op_model_a
thlon
.c
→
arch/x86/oprofile/op_model_a
md
.c
View file @
c00193f9
This diff is collapsed.
Click to expand it.
arch/x86/oprofile/op_x86_model.h
View file @
c00193f9
...
...
@@ -32,6 +32,8 @@ struct pt_regs;
* various x86 CPU models' perfctr support.
*/
struct
op_x86_model_spec
{
int
(
*
init
)(
struct
oprofile_operations
*
ops
);
void
(
*
exit
)(
void
);
unsigned
int
const
num_counters
;
unsigned
int
const
num_controls
;
void
(
*
fill_in_addresses
)(
struct
op_msrs
*
const
msrs
);
...
...
@@ -46,6 +48,6 @@ struct op_x86_model_spec {
extern
struct
op_x86_model_spec
const
op_ppro_spec
;
extern
struct
op_x86_model_spec
const
op_p4_spec
;
extern
struct
op_x86_model_spec
const
op_p4_ht2_spec
;
extern
struct
op_x86_model_spec
const
op_a
thlon
_spec
;
extern
struct
op_x86_model_spec
const
op_a
md
_spec
;
#endif
/* OP_X86_MODEL_H */
arch/x86/pci/fixup.c
View file @
c00193f9
...
...
@@ -511,3 +511,31 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, fam10h_pci_cfg_space_size);
DECLARE_PCI_FIXUP_HEADER
(
PCI_VENDOR_ID_AMD
,
0x1202
,
fam10h_pci_cfg_space_size
);
DECLARE_PCI_FIXUP_HEADER
(
PCI_VENDOR_ID_AMD
,
0x1203
,
fam10h_pci_cfg_space_size
);
DECLARE_PCI_FIXUP_HEADER
(
PCI_VENDOR_ID_AMD
,
0x1204
,
fam10h_pci_cfg_space_size
);
/*
* SB600: Disable BAR1 on device 14.0 to avoid HPET resources from
* confusing the PCI engine:
*/
static
void
sb600_disable_hpet_bar
(
struct
pci_dev
*
dev
)
{
u8
val
;
/*
* The SB600 and SB700 both share the same device
* ID, but the PM register 0x55 does something different
* for the SB700, so make sure we are dealing with the
* SB600 before touching the bit:
*/
pci_read_config_byte
(
dev
,
0x08
,
&
val
);
if
(
val
<
0x2F
)
{
outb
(
0x55
,
0xCD6
);
val
=
inb
(
0xCD7
);
/* Set bit 7 in PM register 0x55 */
outb
(
0x55
,
0xCD6
);
outb
(
val
|
0x80
,
0xCD7
);
}
}
DECLARE_PCI_FIXUP_EARLY
(
PCI_VENDOR_ID_ATI
,
0x4385
,
sb600_disable_hpet_bar
);
drivers/char/hpet.c
View file @
c00193f9
...
...
@@ -53,6 +53,11 @@
#define HPET_RANGE_SIZE 1024
/* from HPET spec */
/* WARNING -- don't get confused. These macros are never used
* to write the (single) counter, and rarely to read it.
* They're badly named; to fix, someday.
*/
#if BITS_PER_LONG == 64
#define write_counter(V, MC) writeq(V, MC)
#define read_counter(MC) readq(MC)
...
...
@@ -77,7 +82,7 @@ static struct clocksource clocksource_hpet = {
.
rating
=
250
,
.
read
=
read_hpet
,
.
mask
=
CLOCKSOURCE_MASK
(
64
),
.
mult
=
0
,
/*to be caluclated
*/
.
mult
=
0
,
/* to be calculated
*/
.
shift
=
10
,
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
};
...
...
@@ -86,8 +91,6 @@ static struct clocksource *hpet_clocksource;
/* A lock for concurrent access by app and isr hpet activity. */
static
DEFINE_SPINLOCK
(
hpet_lock
);
/* A lock for concurrent intermodule access to hpet and isr hpet activity. */
static
DEFINE_SPINLOCK
(
hpet_task_lock
);
#define HPET_DEV_NAME (7)
...
...
@@ -99,7 +102,6 @@ struct hpet_dev {
unsigned
long
hd_irqdata
;
wait_queue_head_t
hd_waitqueue
;
struct
fasync_struct
*
hd_async_queue
;
struct
hpet_task
*
hd_task
;
unsigned
int
hd_flags
;
unsigned
int
hd_irq
;
unsigned
int
hd_hdwirq
;
...
...
@@ -173,11 +175,6 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
writel
(
isr
,
&
devp
->
hd_hpet
->
hpet_isr
);
spin_unlock
(
&
hpet_lock
);
spin_lock
(
&
hpet_task_lock
);
if
(
devp
->
hd_task
)
devp
->
hd_task
->
ht_func
(
devp
->
hd_task
->
ht_data
);
spin_unlock
(
&
hpet_task_lock
);
wake_up_interruptible
(
&
devp
->
hd_waitqueue
);
kill_fasync
(
&
devp
->
hd_async_queue
,
SIGIO
,
POLL_IN
);
...
...
@@ -185,6 +182,67 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
return
IRQ_HANDLED
;
}
static
void
hpet_timer_set_irq
(
struct
hpet_dev
*
devp
)
{
unsigned
long
v
;
int
irq
,
gsi
;
struct
hpet_timer
__iomem
*
timer
;
spin_lock_irq
(
&
hpet_lock
);
if
(
devp
->
hd_hdwirq
)
{
spin_unlock_irq
(
&
hpet_lock
);
return
;
}
timer
=
devp
->
hd_timer
;
/* we prefer level triggered mode */
v
=
readl
(
&
timer
->
hpet_config
);
if
(
!
(
v
&
Tn_INT_TYPE_CNF_MASK
))
{
v
|=
Tn_INT_TYPE_CNF_MASK
;
writel
(
v
,
&
timer
->
hpet_config
);
}
spin_unlock_irq
(
&
hpet_lock
);
v
=
(
readq
(
&
timer
->
hpet_config
)
&
Tn_INT_ROUTE_CAP_MASK
)
>>
Tn_INT_ROUTE_CAP_SHIFT
;
/*
* In PIC mode, skip IRQ0-4, IRQ6-9, IRQ12-15 which is always used by
* legacy device. In IO APIC mode, we skip all the legacy IRQS.
*/
if
(
acpi_irq_model
==
ACPI_IRQ_MODEL_PIC
)
v
&=
~
0xf3df
;
else
v
&=
~
0xffff
;
for
(
irq
=
find_first_bit
(
&
v
,
HPET_MAX_IRQ
);
irq
<
HPET_MAX_IRQ
;
irq
=
find_next_bit
(
&
v
,
HPET_MAX_IRQ
,
1
+
irq
))
{
if
(
irq
>=
NR_IRQS
)
{
irq
=
HPET_MAX_IRQ
;
break
;
}
gsi
=
acpi_register_gsi
(
irq
,
ACPI_LEVEL_SENSITIVE
,
ACPI_ACTIVE_LOW
);
if
(
gsi
>
0
)
break
;
/* FIXME: Setup interrupt source table */
}
if
(
irq
<
HPET_MAX_IRQ
)
{
spin_lock_irq
(
&
hpet_lock
);
v
=
readl
(
&
timer
->
hpet_config
);
v
|=
irq
<<
Tn_INT_ROUTE_CNF_SHIFT
;
writel
(
v
,
&
timer
->
hpet_config
);
devp
->
hd_hdwirq
=
gsi
;
spin_unlock_irq
(
&
hpet_lock
);
}
return
;
}
static
int
hpet_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
hpet_dev
*
devp
;
...
...
@@ -199,8 +257,7 @@ static int hpet_open(struct inode *inode, struct file *file)
for
(
devp
=
NULL
,
hpetp
=
hpets
;
hpetp
&&
!
devp
;
hpetp
=
hpetp
->
hp_next
)
for
(
i
=
0
;
i
<
hpetp
->
hp_ntimer
;
i
++
)
if
(
hpetp
->
hp_dev
[
i
].
hd_flags
&
HPET_OPEN
||
hpetp
->
hp_dev
[
i
].
hd_task
)
if
(
hpetp
->
hp_dev
[
i
].
hd_flags
&
HPET_OPEN
)
continue
;
else
{
devp
=
&
hpetp
->
hp_dev
[
i
];
...
...
@@ -219,6 +276,8 @@ static int hpet_open(struct inode *inode, struct file *file)
spin_unlock_irq
(
&
hpet_lock
);
unlock_kernel
();
hpet_timer_set_irq
(
devp
);
return
0
;
}
...
...
@@ -441,7 +500,11 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
devp
->
hd_irq
=
irq
;
t
=
devp
->
hd_ireqfreq
;
v
=
readq
(
&
timer
->
hpet_config
);
g
=
v
|
Tn_INT_ENB_CNF_MASK
;
/* 64-bit comparators are not yet supported through the ioctls,
* so force this into 32-bit mode if it supports both modes
*/
g
=
v
|
Tn_32MODE_CNF_MASK
|
Tn_INT_ENB_CNF_MASK
;
if
(
devp
->
hd_flags
&
HPET_PERIODIC
)
{
write_counter
(
t
,
&
timer
->
hpet_compare
);
...
...
@@ -451,6 +514,12 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
v
|=
Tn_VAL_SET_CNF_MASK
;
writeq
(
v
,
&
timer
->
hpet_config
);
local_irq_save
(
flags
);
/* NOTE: what we modify here is a hidden accumulator
* register supported by periodic-capable comparators.
* We never want to modify the (single) counter; that
* would affect all the comparators.
*/
m
=
read_counter
(
&
hpet
->
hpet_mc
);
write_counter
(
t
+
m
+
hpetp
->
hp_delta
,
&
timer
->
hpet_compare
);
}
else
{
...
...
@@ -604,57 +673,6 @@ static int hpet_is_known(struct hpet_data *hdp)
return
0
;
}
static
inline
int
hpet_tpcheck
(
struct
hpet_task
*
tp
)
{
struct
hpet_dev
*
devp
;
struct
hpets
*
hpetp
;
devp
=
tp
->
ht_opaque
;
if
(
!
devp
)
return
-
ENXIO
;
for
(
hpetp
=
hpets
;
hpetp
;
hpetp
=
hpetp
->
hp_next
)
if
(
devp
>=
hpetp
->
hp_dev
&&
devp
<
(
hpetp
->
hp_dev
+
hpetp
->
hp_ntimer
)
&&
devp
->
hd_hpet
==
hpetp
->
hp_hpet
)
return
0
;
return
-
ENXIO
;
}
#if 0
int hpet_unregister(struct hpet_task *tp)
{
struct hpet_dev *devp;
struct hpet_timer __iomem *timer;
int err;
if ((err = hpet_tpcheck(tp)))
return err;
spin_lock_irq(&hpet_task_lock);
spin_lock(&hpet_lock);
devp = tp->ht_opaque;
if (devp->hd_task != tp) {
spin_unlock(&hpet_lock);
spin_unlock_irq(&hpet_task_lock);
return -ENXIO;
}
timer = devp->hd_timer;
writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
&timer->hpet_config);
devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC);
devp->hd_task = NULL;
spin_unlock(&hpet_lock);
spin_unlock_irq(&hpet_task_lock);
return 0;
}
#endif /* 0 */
static
ctl_table
hpet_table
[]
=
{
{
.
ctl_name
=
CTL_UNNUMBERED
,
...
...
@@ -746,6 +764,7 @@ int hpet_alloc(struct hpet_data *hdp)
static
struct
hpets
*
last
=
NULL
;
unsigned
long
period
;
unsigned
long
long
temp
;
u32
remainder
;
/*
* hpet_alloc can be called by platform dependent code.
...
...
@@ -809,9 +828,13 @@ int hpet_alloc(struct hpet_data *hdp)
printk
(
"%s %d"
,
i
>
0
?
","
:
""
,
hdp
->
hd_irq
[
i
]);
printk
(
"
\n
"
);
printk
(
KERN_INFO
"hpet%u: %u %d-bit timers, %Lu Hz
\n
"
,
hpetp
->
hp_which
,
hpetp
->
hp_ntimer
,
cap
&
HPET_COUNTER_SIZE_MASK
?
64
:
32
,
hpetp
->
hp_tick_freq
);
temp
=
hpetp
->
hp_tick_freq
;
remainder
=
do_div
(
temp
,
1000000
);
printk
(
KERN_INFO
"hpet%u: %u comparators, %d-bit %u.%06u MHz counter
\n
"
,
hpetp
->
hp_which
,
hpetp
->
hp_ntimer
,
cap
&
HPET_COUNTER_SIZE_MASK
?
64
:
32
,
(
unsigned
)
temp
,
remainder
);
mcfg
=
readq
(
&
hpet
->
hpet_config
);
if
((
mcfg
&
HPET_ENABLE_CNF_MASK
)
==
0
)
{
...
...
@@ -874,8 +897,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
hdp
->
hd_address
=
ioremap
(
addr
.
minimum
,
addr
.
address_length
);
if
(
hpet_is_known
(
hdp
))
{
printk
(
KERN_DEBUG
"%s: 0x%lx is busy
\n
"
,
__func__
,
hdp
->
hd_phys_address
);
iounmap
(
hdp
->
hd_address
);
return
AE_ALREADY_EXISTS
;
}
...
...
@@ -891,8 +912,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
HPET_RANGE_SIZE
);
if
(
hpet_is_known
(
hdp
))
{
printk
(
KERN_DEBUG
"%s: 0x%lx is busy
\n
"
,
__func__
,
hdp
->
hd_phys_address
);
iounmap
(
hdp
->
hd_address
);
return
AE_ALREADY_EXISTS
;
}
...
...
drivers/oprofile/buffer_sync.c
View file @
c00193f9
This diff is collapsed.
Click to expand it.
drivers/oprofile/cpu_buffer.c
View file @
c00193f9
...
...
@@ -5,6 +5,7 @@
* @remark Read the file COPYING
*
* @author John Levon <levon@movementarian.org>
* @author Barry Kasindorf <barry.kasindorf@amd.com>
*
* Each CPU has a local buffer that stores PC value/event
* pairs. We also log context switches when we notice them.
...
...
@@ -209,7 +210,7 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc,
return
1
;
}
static
int
oprofile_begin_trace
(
struct
oprofile_cpu_buffer
*
cpu_buf
)
static
int
oprofile_begin_trace
(
struct
oprofile_cpu_buffer
*
cpu_buf
)
{
if
(
nr_available_slots
(
cpu_buf
)
<
4
)
{
cpu_buf
->
sample_lost_overflow
++
;
...
...
@@ -254,6 +255,75 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
oprofile_add_ext_sample
(
pc
,
regs
,
event
,
is_kernel
);
}
#ifdef CONFIG_OPROFILE_IBS
#define MAX_IBS_SAMPLE_SIZE 14
static
int
log_ibs_sample
(
struct
oprofile_cpu_buffer
*
cpu_buf
,
unsigned
long
pc
,
int
is_kernel
,
unsigned
int
*
ibs
,
int
ibs_code
)
{
struct
task_struct
*
task
;
cpu_buf
->
sample_received
++
;
if
(
nr_available_slots
(
cpu_buf
)
<
MAX_IBS_SAMPLE_SIZE
)
{
cpu_buf
->
sample_lost_overflow
++
;
return
0
;
}
is_kernel
=
!!
is_kernel
;
/* notice a switch from user->kernel or vice versa */
if
(
cpu_buf
->
last_is_kernel
!=
is_kernel
)
{
cpu_buf
->
last_is_kernel
=
is_kernel
;
add_code
(
cpu_buf
,
is_kernel
);
}
/* notice a task switch */
if
(
!
is_kernel
)
{
task
=
current
;
if
(
cpu_buf
->
last_task
!=
task
)
{
cpu_buf
->
last_task
=
task
;
add_code
(
cpu_buf
,
(
unsigned
long
)
task
);
}
}
add_code
(
cpu_buf
,
ibs_code
);
add_sample
(
cpu_buf
,
ibs
[
0
],
ibs
[
1
]);
add_sample
(
cpu_buf
,
ibs
[
2
],
ibs
[
3
]);
add_sample
(
cpu_buf
,
ibs
[
4
],
ibs
[
5
]);
if
(
ibs_code
==
IBS_OP_BEGIN
)
{
add_sample
(
cpu_buf
,
ibs
[
6
],
ibs
[
7
]);
add_sample
(
cpu_buf
,
ibs
[
8
],
ibs
[
9
]);
add_sample
(
cpu_buf
,
ibs
[
10
],
ibs
[
11
]);
}
return
1
;
}
void
oprofile_add_ibs_sample
(
struct
pt_regs
*
const
regs
,
unsigned
int
*
const
ibs_sample
,
u8
code
)
{
int
is_kernel
=
!
user_mode
(
regs
);
unsigned
long
pc
=
profile_pc
(
regs
);
struct
oprofile_cpu_buffer
*
cpu_buf
=
&
per_cpu
(
cpu_buffer
,
smp_processor_id
());
if
(
!
backtrace_depth
)
{
log_ibs_sample
(
cpu_buf
,
pc
,
is_kernel
,
ibs_sample
,
code
);
return
;
}
/* if log_sample() fails we can't backtrace since we lost the source
* of this event */
if
(
log_ibs_sample
(
cpu_buf
,
pc
,
is_kernel
,
ibs_sample
,
code
))
oprofile_ops
.
backtrace
(
regs
,
backtrace_depth
);
}
#endif
void
oprofile_add_pc
(
unsigned
long
pc
,
int
is_kernel
,
unsigned
long
event
)
{
struct
oprofile_cpu_buffer
*
cpu_buf
=
&
__get_cpu_var
(
cpu_buffer
);
...
...
@@ -296,7 +366,7 @@ static void wq_sync_buffer(struct work_struct *work)
struct
oprofile_cpu_buffer
*
b
=
container_of
(
work
,
struct
oprofile_cpu_buffer
,
work
.
work
);
if
(
b
->
cpu
!=
smp_processor_id
())
{
printk
(
"WQ on CPU%d, prefer CPU%d
\n
"
,
printk
(
KERN_DEBUG
"WQ on CPU%d, prefer CPU%d
\n
"
,
smp_processor_id
(),
b
->
cpu
);
}
sync_buffer
(
b
->
cpu
);
...
...
drivers/oprofile/cpu_buffer.h
View file @
c00193f9
...
...
@@ -55,5 +55,7 @@ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
/* transient events for the CPU buffer -> event buffer */
#define CPU_IS_KERNEL 1
#define CPU_TRACE_BEGIN 2
#define IBS_FETCH_BEGIN 3
#define IBS_OP_BEGIN 4
#endif
/* OPROFILE_CPU_BUFFER_H */
include/linux/hpet.h
View file @
c00193f9
...
...
@@ -37,6 +37,7 @@ struct hpet {
#define hpet_compare _u1._hpet_compare
#define HPET_MAX_TIMERS (32)
#define HPET_MAX_IRQ (32)
/*
* HPET general capabilities register
...
...
@@ -64,7 +65,7 @@ struct hpet {
*/
#define Tn_INT_ROUTE_CAP_MASK (0xffffffff00000000ULL)
#define Tn_IN
I
_ROUTE_CAP_SHIFT (32UL)
#define Tn_IN
T
_ROUTE_CAP_SHIFT (32UL)
#define Tn_FSB_INT_DELCAP_MASK (0x8000UL)
#define Tn_FSB_INT_DELCAP_SHIFT (15)
#define Tn_FSB_EN_CNF_MASK (0x4000UL)
...
...
@@ -91,23 +92,14 @@ struct hpet {
* exported interfaces
*/
struct
hpet_task
{
void
(
*
ht_func
)
(
void
*
);
void
*
ht_data
;
void
*
ht_opaque
;
};
struct
hpet_data
{
unsigned
long
hd_phys_address
;
void
__iomem
*
hd_address
;
unsigned
short
hd_nirqs
;
unsigned
short
hd_flags
;
unsigned
int
hd_state
;
/* timer allocated */
unsigned
int
hd_irq
[
HPET_MAX_TIMERS
];
};
#define HPET_DATA_PLATFORM 0x0001
/* platform call to hpet_alloc */
static
inline
void
hpet_reserve_timer
(
struct
hpet_data
*
hd
,
int
timer
)
{
hd
->
hd_state
|=
(
1
<<
timer
);
...
...
@@ -125,7 +117,7 @@ struct hpet_info {
unsigned
short
hi_timer
;
};
#define
HPET_INFO_PERIODIC 0x0001
/* timer is periodic
*/
#define
HPET_INFO_PERIODIC 0x0010
/* periodic-capable comparator
*/
#define HPET_IE_ON _IO('h', 0x01)
/* interrupt on */
#define HPET_IE_OFF _IO('h', 0x02)
/* interrupt off */
...
...
include/linux/oprofile.h
View file @
c00193f9
...
...
@@ -36,6 +36,8 @@
#define XEN_ENTER_SWITCH_CODE 10
#define SPU_PROFILING_CODE 11
#define SPU_CTX_SWITCH_CODE 12
#define IBS_FETCH_CODE 13
#define IBS_OP_CODE 14
struct
super_block
;
struct
dentry
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment