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
nexedi
linux
Commits
34df7e4e
Commit
34df7e4e
authored
Sep 03, 2002
by
David Mosberger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ia64: First draft of perfmon sampling-interval randomization support.
parent
5321ba97
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
112 additions
and
39 deletions
+112
-39
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/perfmon.c
+38
-21
arch/ia64/lib/Makefile
arch/ia64/lib/Makefile
+1
-0
arch/ia64/lib/carta_random.S
arch/ia64/lib/carta_random.S
+54
-0
include/asm-ia64/perfmon.h
include/asm-ia64/perfmon.h
+19
-18
No files found.
arch/ia64/kernel/perfmon.c
View file @
34df7e4e
...
...
@@ -193,10 +193,12 @@ typedef enum {
*/
typedef
struct
{
u64
val
;
/* virtual 64bit counter value */
u64
ival
;
/* initial value from user
*/
u64
lval
;
/* last value
*/
u64
long_reset
;
/* reset value on sampling overflow */
u64
short_reset
;
/* reset value on overflow */
u64
reset_pmds
[
4
];
/* which other pmds to reset when this counter overflows */
u64
seed
;
/* seed for random-number generator */
u64
mask
;
/* mask for random-number generator */
int
flags
;
/* notify/do not notify */
}
pfm_counter_t
;
...
...
@@ -1150,13 +1152,32 @@ pfm_context_create(struct task_struct *task, pfm_context_t *ctx, void *req, int
return
ret
;
}
static
inline
unsigned
long
new_counter_value
(
pfm_counter_t
*
reg
,
int
is_long_reset
)
{
unsigned
long
val
=
is_long_reset
?
reg
->
long_reset
:
reg
->
short_reset
;
unsigned
long
new_seed
,
old_seed
=
reg
->
seed
,
mask
=
reg
->
mask
;
extern
unsigned
long
carta_random32
(
unsigned
long
seed
);
if
(
reg
->
flags
&
PFM_REGFL_RANDOM
)
{
new_seed
=
carta_random32
(
old_seed
);
val
-=
(
old_seed
&
mask
);
/* counter values are negative numbers! */
if
((
mask
>>
32
)
!=
0
)
/* construct a full 64-bit random value: */
new_seed
|=
carta_random32
(
old_seed
>>
32
)
<<
32
;
reg
->
seed
=
new_seed
;
}
reg
->
lval
=
val
;
return
val
;
}
static
void
pfm_reset_regs
(
pfm_context_t
*
ctx
,
unsigned
long
*
ovfl_regs
,
int
flag
)
{
unsigned
long
mask
=
ovfl_regs
[
0
];
unsigned
long
reset_others
=
0UL
;
unsigned
long
val
;
int
i
;
int
i
,
is_long_reset
=
(
flag
&
PFM_RELOAD_LONG_RESET
)
;
DBprintk
((
"masks=0x%lx
\n
"
,
mask
));
...
...
@@ -1166,15 +1187,11 @@ pfm_reset_regs(pfm_context_t *ctx, unsigned long *ovfl_regs, int flag)
mask
>>=
PMU_FIRST_COUNTER
;
for
(
i
=
PMU_FIRST_COUNTER
;
mask
;
i
++
,
mask
>>=
1
)
{
if
(
mask
&
0x1
)
{
val
=
flag
==
PFM_RELOAD_LONG_RESET
?
ctx
->
ctx_soft_pmds
[
i
].
long_reset
:
ctx
->
ctx_soft_pmds
[
i
].
short_reset
;
val
=
new_counter_value
(
ctx
->
ctx_soft_pmds
+
i
,
is_long_reset
);
reset_others
|=
ctx
->
ctx_soft_pmds
[
i
].
reset_pmds
[
0
];
DBprintk
((
"[%d] %s reset soft_pmd[%d]=%lx
\n
"
,
current
->
pid
,
flag
==
PFM_RELOAD_LONG_RESET
?
"long"
:
"short"
,
i
,
val
));
DBprintk
((
"[%d] %s reset soft_pmd[%d]=%lx
\n
"
,
current
->
pid
,
is_long_reset
?
"long"
:
"short"
,
i
,
val
));
/* upper part is ignored on rval */
pfm_write_soft_counter
(
ctx
,
i
,
val
);
...
...
@@ -1188,19 +1205,15 @@ pfm_reset_regs(pfm_context_t *ctx, unsigned long *ovfl_regs, int flag)
if
((
reset_others
&
0x1
)
==
0
)
continue
;
val
=
flag
==
PFM_RELOAD_LONG_RESET
?
ctx
->
ctx_soft_pmds
[
i
].
long_reset
:
ctx
->
ctx_soft_pmds
[
i
].
short_reset
;
val
=
new_counter_value
(
ctx
->
ctx_soft_pmds
+
i
,
is_long_reset
);
if
(
PMD_IS_COUNTING
(
i
))
{
pfm_write_soft_counter
(
ctx
,
i
,
val
);
}
else
{
ia64_set_pmd
(
i
,
val
);
}
DBprintk
((
"[%d] %s reset_others pmd[%d]=%lx
\n
"
,
current
->
pid
,
flag
==
PFM_RELOAD_LONG_RESET
?
"long"
:
"short"
,
i
,
val
));
DBprintk
((
"[%d] %s reset_others pmd[%d]=%lx
\n
"
,
current
->
pid
,
is_long_reset
?
"long"
:
"short"
,
i
,
val
));
}
ia64_srlz_d
();
/* just in case ! */
...
...
@@ -1283,6 +1296,9 @@ pfm_write_pmcs(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun
ctx
->
ctx_soft_pmds
[
cnum
].
reset_pmds
[
1
]
=
tmp
.
reg_reset_pmds
[
1
];
ctx
->
ctx_soft_pmds
[
cnum
].
reset_pmds
[
2
]
=
tmp
.
reg_reset_pmds
[
2
];
ctx
->
ctx_soft_pmds
[
cnum
].
reset_pmds
[
3
]
=
tmp
.
reg_reset_pmds
[
3
];
if
(
tmp
.
reg_flags
&
PFM_REGFL_RANDOM
)
ctx
->
ctx_soft_pmds
[
cnum
].
flags
|=
PFM_REGFL_RANDOM
;
}
/*
* execute write checker, if any
...
...
@@ -1369,11 +1385,12 @@ pfm_write_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun
/* update virtualized (64bits) counter */
if
(
PMD_IS_COUNTING
(
cnum
))
{
ctx
->
ctx_soft_pmds
[
cnum
].
i
val
=
tmp
.
reg_value
;
ctx
->
ctx_soft_pmds
[
cnum
].
l
val
=
tmp
.
reg_value
;
ctx
->
ctx_soft_pmds
[
cnum
].
val
=
tmp
.
reg_value
&
~
pmu_conf
.
perf_ovfl_val
;
ctx
->
ctx_soft_pmds
[
cnum
].
long_reset
=
tmp
.
reg_long_reset
;
ctx
->
ctx_soft_pmds
[
cnum
].
short_reset
=
tmp
.
reg_short_reset
;
ctx
->
ctx_soft_pmds
[
cnum
].
seed
=
tmp
.
reserved
[
0
];
ctx
->
ctx_soft_pmds
[
cnum
].
mask
=
tmp
.
reserved
[
1
];
}
/*
* execute write checker, if any
...
...
@@ -2554,7 +2571,7 @@ pfm_record_sample(struct task_struct *task, pfm_context_t *ctx, unsigned long ov
*/
h
->
pid
=
current
->
pid
;
h
->
cpu
=
smp_processor_id
();
h
->
rate
=
0
;
/* XXX: add the sampling rate used here */
h
->
last_reset_value
=
ovfl_mask
?
ctx
->
ctx_soft_pmds
[
ffz
(
~
ovfl_mask
)].
lval
:
0
;
h
->
ip
=
regs
?
regs
->
cr_iip
:
0x0
;
/* where did the fault happened */
h
->
regs
=
ovfl_mask
;
/* which registers overflowed */
...
...
@@ -3769,8 +3786,8 @@ pfm_inherit(struct task_struct *task, struct pt_regs *regs)
m
=
nctx
->
ctx_used_pmds
[
0
]
>>
PMU_FIRST_COUNTER
;
for
(
i
=
PMU_FIRST_COUNTER
;
m
;
m
>>=
1
,
i
++
)
{
if
((
m
&
0x1
)
&&
pmu_conf
.
pmd_desc
[
i
].
type
==
PFM_REG_COUNTING
)
{
nctx
->
ctx_soft_pmds
[
i
].
val
=
nctx
->
ctx_soft_pmds
[
i
].
i
val
&
~
pmu_conf
.
perf_ovfl_val
;
thread
->
pmd
[
i
]
=
nctx
->
ctx_soft_pmds
[
i
].
i
val
&
pmu_conf
.
perf_ovfl_val
;
nctx
->
ctx_soft_pmds
[
i
].
val
=
nctx
->
ctx_soft_pmds
[
i
].
l
val
&
~
pmu_conf
.
perf_ovfl_val
;
thread
->
pmd
[
i
]
=
nctx
->
ctx_soft_pmds
[
i
].
l
val
&
pmu_conf
.
perf_ovfl_val
;
}
/* what about the other pmds? zero or keep as is */
...
...
arch/ia64/lib/Makefile
View file @
34df7e4e
...
...
@@ -15,6 +15,7 @@ obj-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
obj-$(CONFIG_ITANIUM)
+=
copy_page.o copy_user.o memcpy.o
obj-$(CONFIG_MCKINLEY)
+=
copy_page_mck.o memcpy_mck.o
obj-$(CONFIG_PERFMON)
+=
carta_random.o
IGNORE_FLAGS_OBJS
=
__divsi3.o __udivsi3.o __modsi3.o __umodsi3.o
\
__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o
...
...
arch/ia64/lib/carta_random.S
0 → 100644
View file @
34df7e4e
/*
*
Fast
,
simple
,
yet
decent
quality
random
number
generator
based
on
*
a
paper
by
David
G
.
Carta
(
"Two Fast Implementations of the
*
`
Minimal
Standard
' Random Number Generator," Communications of the
*
ACM
,
January
,
1990
)
.
*
*
Copyright
(
C
)
2002
Hewlett
-
Packard
Co
*
David
Mosberger
-
Tang
<
davidm
@
hpl
.
hp
.
com
>
*/
#include <asm/asmmacro.h>
#define a r2
#define m r3
#define lo r8
#define hi r9
#define t0 r16
#define t1 r17
#define seed r32
GLOBAL_ENTRY
(
carta_random32
)
movl
a
=
(
16807
<<
16
)
|
16807
;;
pmpyshr2.u
t0
=
a
,
seed
,
0
pmpyshr2.u
t1
=
a
,
seed
,
16
;;
unpack2.l
t0
=
t1
,
t0
dep
m
=
-
1
,
r0
,
0
,
31
;;
zxt4
lo
=
t0
shr.u
hi
=
t0
,
32
;;
dep
t0
=
0
,
hi
,
15
,
49
//
t0
=
(
hi
&
0x7fff
)
;;
shl
t0
=
t0
,
16
//
t0
=
(
hi
&
0x7fff
)
<<
16
shr
t1
=
hi
,
15
//
t1
=
(
hi
>>
15
)
;;
add
lo
=
lo
,
t0
;;
cmp.gtu
p6
,
p0
=
lo
,
m
;;
(
p6
)
and
lo
=
lo
,
m
;;
(
p6
)
add
lo
=
1
,
lo
;;
add
lo
=
lo
,
t1
;;
cmp.gtu
p6
,
p0
=
lo
,
m
;;
(
p6
)
and
lo
=
lo
,
m
;;
(
p6
)
add
lo
=
1
,
lo
br.ret.sptk.many
rp
END
(
carta_random32
)
include/asm-ia64/perfmon.h
View file @
34df7e4e
...
...
@@ -45,6 +45,7 @@
* PMC flags
*/
#define PFM_REGFL_OVFL_NOTIFY 0x1
/* send notification on overflow */
#define PFM_REGFL_RANDOM 0x2
/* randomize sampling interval */
/*
* PMD/PMC/IBR/DBR return flags (ignored on input)
...
...
@@ -132,28 +133,28 @@ typedef struct {
#define PFM_VERSION_MINOR(x) ((x) & 0xffff)
/*
* Entry header in the sampling buffer.
*
The header is directly followed with the PMDS saved in increasing index
*
order: PMD4, PMD5, .... How many PMDs are present is determined by the
*
user program during
context creation.
* Entry header in the sampling buffer.
The header is directly followed
*
with the PMDs saved in increasing index order: PMD4, PMD5, .... How
*
many PMDs are present is determined by the user program during
* context creation.
*
* XXX: in this version of the entry, only up to 64 registers can be
recorded
*
This should be enough for quite some time. Always check sampling format
* before parsing entries!
* XXX: in this version of the entry, only up to 64 registers can be
*
recorded. This should be enough for quite some time. Always check
*
sampling format
before parsing entries!
*
* In
n the case where multiple counters have overflowed at the same time, the
*
rate field indicate the initial value of the first PMD, based on the index.
*
For instance, if PMD2 and PMD5 have ovewrflowed for this entry, the rate field
*
will show
the initial value of PMD2.
* In
the case where multiple counters overflow at the same time, the
*
last_reset_value member indicates the initial value of the PMD with
*
the smallest index. For instance, if PMD2 and PMD5 have overflowed,
*
the last_reset_value member contains
the initial value of PMD2.
*/
typedef
struct
{
int
pid
;
/* identification of process */
int
cpu
;
/* which cpu was used */
unsigned
long
rate
;
/* initial value of overflowed counter
*/
unsigned
long
stamp
;
/* timestamp */
unsigned
long
ip
;
/* where did the overflow interrupt happened */
unsigned
long
regs
;
/* bitmask of which registers overflowed */
unsigned
long
period
;
/* sampling period used by overflowed counter (smallest pmd index)
*/
int
pid
;
/* identification of process */
int
cpu
;
/* which cpu was used */
unsigned
long
last_reset_value
;
/* initial value of counter that overflowed
*/
unsigned
long
stamp
;
/* timestamp */
unsigned
long
ip
;
/* where did the overflow interrupt happened */
unsigned
long
regs
;
/* bitmask of which registers overflowed */
unsigned
long
period
;
/* unused
*/
}
perfmon_smpl_entry_t
;
extern
int
perfmonctl
(
pid_t
pid
,
int
cmd
,
void
*
arg
,
int
narg
);
...
...
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