Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
63ef3482
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
63ef3482
编写于
16年前
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
sparc64: Provide oprofile pseudo-NMI on Niagara.
Signed-off-by:
N
David S. Miller
<
davem@davemloft.net
>
上级
3178a07c
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
135 addition
and
16 deletion
+135
-16
arch/sparc/oprofile/init.c
arch/sparc/oprofile/init.c
+135
-16
未找到文件。
arch/sparc/oprofile/init.c
浏览文件 @
63ef3482
...
...
@@ -13,32 +13,97 @@
#include <linux/init.h>
#ifdef CONFIG_SPARC64
#include <asm/hypervisor.h>
#include <asm/spitfire.h>
#include <asm/cpudata.h>
#include <asm/irq.h>
static
int
nmi_enabled
;
struct
pcr_ops
{
u64
(
*
read
)(
void
);
void
(
*
write
)(
u64
);
};
static
const
struct
pcr_ops
*
pcr_ops
;
static
u64
direct_pcr_read
(
void
)
{
u64
val
;
read_pcr
(
val
);
return
val
;
}
static
void
direct_pcr_write
(
u64
val
)
{
write_pcr
(
val
);
}
static
const
struct
pcr_ops
direct_pcr_ops
=
{
.
read
=
direct_pcr_read
,
.
write
=
direct_pcr_write
,
};
static
void
n2_pcr_write
(
u64
val
)
{
unsigned
long
ret
;
ret
=
sun4v_niagara2_setperf
(
HV_N2_PERF_SPARC_CTL
,
val
);
if
(
val
!=
HV_EOK
)
write_pcr
(
val
);
}
static
const
struct
pcr_ops
n2_pcr_ops
=
{
.
read
=
direct_pcr_read
,
.
write
=
n2_pcr_write
,
};
/* In order to commonize as much of the implementation as
* possible, we use PICH as our counter. Mostly this is
* to accomodate Niagara-1 which can only count insn cycles
* in PICH.
*/
static
u64
picl_value
(
void
)
{
u32
delta
=
local_cpu_data
().
clock_tick
/
HZ
;
return
(
0
-
delta
)
&
0xffffffff
;
return
(
(
u64
)((
0
-
delta
)
&
0xffffffff
))
<<
32
;
}
#define PCR_PIC_PRIV 0x1
/* PIC access is privileged */
#define PCR_STRACE 0x2
/* Trace supervisor events */
#define PCR_UTRACE 0x4
/* Trace user events */
#define PCR_PIC_PRIV 0x00000001
/* PIC access is privileged */
#define PCR_STRACE 0x00000002
/* Trace supervisor events */
#define PCR_UTRACE 0x00000004
/* Trace user events */
#define PCR_N2_HTRACE 0x00000008
/* Trace hypervisor events */
#define PCR_N2_TOE_OV0 0x00000010
/* Trap if PIC 0 overflows */
#define PCR_N2_TOE_OV1 0x00000020
/* Trap if PIC 1 overflows */
#define PCR_N2_MASK0 0x00003fc0
#define PCR_N2_MASK0_SHIFT 6
#define PCR_N2_SL0 0x0003c000
#define PCR_N2_SL0_SHIFT 14
#define PCR_N2_OV0 0x00040000
#define PCR_N2_MASK1 0x07f80000
#define PCR_N2_MASK1_SHIFT 19
#define PCR_N2_SL1 0x78000000
#define PCR_N2_SL1_SHIFT 27
#define PCR_N2_OV1 0x80000000
#define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE)
#define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \
PCR_N2_TOE_OV1 | \
(2 << PCR_N2_SL1_SHIFT) | \
(0xff << PCR_N2_MASK1_SHIFT))
static
u64
pcr_enable
=
PCR_SUN4U_ENABLE
;
static
void
nmi_handler
(
struct
pt_regs
*
regs
)
{
write_pcr
(
PCR_PIC_PRIV
);
pcr_ops
->
write
(
PCR_PIC_PRIV
);
if
(
nmi_enabled
)
{
oprofile_add_sample
(
regs
,
0
);
write_pic
(
picl_value
());
write_pcr
(
PCR_PIC_PRIV
|
PCR_STRACE
|
PCR_UTRACE
);
pcr_ops
->
write
(
pcr_enable
);
}
}
...
...
@@ -48,21 +113,15 @@ static void nmi_handler(struct pt_regs *regs)
*/
static
void
cpu_nmi_start
(
void
*
_unused
)
{
write_pcr
(
PCR_PIC_PRIV
);
pcr_ops
->
write
(
PCR_PIC_PRIV
);
write_pic
(
picl_value
());
/* Bit 0: PIC access is privileged
* Bit 1: Supervisor Trace
* Bit 2: User Trace
*
* And the event selection code for cpu cycles is zero.
*/
write_pcr
(
PCR_PIC_PRIV
|
PCR_STRACE
|
PCR_UTRACE
);
pcr_ops
->
write
(
pcr_enable
);
}
static
void
cpu_nmi_stop
(
void
*
_unused
)
{
write_pcr
(
PCR_PIC_PRIV
);
pcr_ops
->
write
(
PCR_PIC_PRIV
);
}
static
int
nmi_start
(
void
)
...
...
@@ -94,10 +153,67 @@ static void nmi_stop(void)
synchronize_sched
();
}
static
unsigned
long
perf_hsvc_group
;
static
unsigned
long
perf_hsvc_major
;
static
unsigned
long
perf_hsvc_minor
;
static
int
__init
register_perf_hsvc
(
void
)
{
if
(
tlb_type
==
hypervisor
)
{
switch
(
sun4v_chip_type
)
{
case
SUN4V_CHIP_NIAGARA1
:
perf_hsvc_group
=
HV_GRP_NIAG_PERF
;
break
;
case
SUN4V_CHIP_NIAGARA2
:
perf_hsvc_group
=
HV_GRP_N2_CPU
;
break
;
default:
return
-
ENODEV
;
}
perf_hsvc_major
=
1
;
perf_hsvc_minor
=
0
;
if
(
sun4v_hvapi_register
(
perf_hsvc_group
,
perf_hsvc_major
,
&
perf_hsvc_minor
))
{
printk
(
"perfmon: Could not register N2 hvapi.
\n
"
);
return
-
ENODEV
;
}
}
return
0
;
}
static
void
unregister_perf_hsvc
(
void
)
{
if
(
tlb_type
!=
hypervisor
)
return
;
sun4v_hvapi_unregister
(
perf_hsvc_group
);
}
static
int
oprofile_nmi_init
(
struct
oprofile_operations
*
ops
)
{
if
(
tlb_type
!=
cheetah
&&
tlb_type
!=
cheetah_plus
)
int
err
=
register_perf_hsvc
();
if
(
err
)
return
err
;
switch
(
tlb_type
)
{
case
hypervisor
:
pcr_ops
=
&
n2_pcr_ops
;
pcr_enable
=
PCR_N2_ENABLE
;
break
;
case
cheetah
:
case
cheetah_plus
:
pcr_ops
=
&
direct_pcr_ops
;
break
;
default:
return
-
ENODEV
;
}
ops
->
create_files
=
NULL
;
ops
->
setup
=
NULL
;
...
...
@@ -128,4 +244,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
void
oprofile_arch_exit
(
void
)
{
#ifdef CONFIG_SPARC64
unregister_perf_hsvc
();
#endif
}
This diff is collapsed.
Click to expand it.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录
新手
引导
客服
返回
顶部