Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
d09c2a23
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d09c2a23
编写于
2月 06, 2008
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[SPARC64]: Add user regsets.
Signed-off-by:
N
David S. Miller
<
davem@davemloft.net
>
上级
ce22e1d3
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
581 addition
and
1 deletion
+581
-1
arch/sparc64/kernel/ptrace.c
arch/sparc64/kernel/ptrace.c
+581
-1
未找到文件。
arch/sparc64/kernel/ptrace.c
浏览文件 @
d09c2a23
/* ptrace.c: Sparc process tracing support.
*
* Copyright (C) 1996
David S. Miller (davem@caipfs.rutgers.edu
)
* Copyright (C) 1996
, 2008 David S. Miller (davem@davemloft.net
)
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*
* Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
...
...
@@ -22,6 +22,9 @@
#include <linux/seccomp.h>
#include <linux/audit.h>
#include <linux/signal.h>
#include <linux/regset.h>
#include <linux/compat.h>
#include <linux/elf.h>
#include <asm/asi.h>
#include <asm/pgtable.h>
...
...
@@ -167,6 +170,583 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
}
}
enum
sparc_regset
{
REGSET_GENERAL
,
REGSET_FP
,
};
static
int
genregs64_get
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
void
*
kbuf
,
void
__user
*
ubuf
)
{
const
struct
pt_regs
*
regs
=
task_pt_regs
(
target
);
int
ret
;
if
(
target
==
current
)
flushw_user
();
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
regs
->
u_regs
,
0
,
16
*
sizeof
(
u64
));
if
(
!
ret
)
{
unsigned
long
__user
*
reg_window
=
(
unsigned
long
__user
*
)
(
regs
->
u_regs
[
UREG_I6
]
+
STACK_BIAS
);
unsigned
long
window
[
16
];
if
(
copy_from_user
(
window
,
reg_window
,
sizeof
(
window
)))
return
-
EFAULT
;
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
window
,
16
*
sizeof
(
u64
),
32
*
sizeof
(
u64
));
}
if
(
!
ret
)
{
/* TSTATE, TPC, TNPC */
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
regs
->
tstate
,
32
*
sizeof
(
u64
),
35
*
sizeof
(
u64
));
}
if
(
!
ret
)
{
unsigned
long
y
=
regs
->
y
;
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
y
,
35
*
sizeof
(
u64
),
36
*
sizeof
(
u64
));
}
if
(
!
ret
)
ret
=
user_regset_copyout_zero
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
36
*
sizeof
(
u64
),
-
1
);
return
ret
;
}
static
int
genregs64_set
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
const
void
*
kbuf
,
const
void
__user
*
ubuf
)
{
struct
pt_regs
*
regs
=
task_pt_regs
(
target
);
int
ret
;
if
(
target
==
current
)
flushw_user
();
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
regs
->
u_regs
,
0
,
16
*
sizeof
(
u64
));
if
(
!
ret
&&
count
>
0
)
{
unsigned
long
__user
*
reg_window
=
(
unsigned
long
__user
*
)
(
regs
->
u_regs
[
UREG_I6
]
+
STACK_BIAS
);
unsigned
long
window
[
16
];
if
(
copy_from_user
(
window
,
reg_window
,
sizeof
(
window
)))
return
-
EFAULT
;
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
window
,
16
*
sizeof
(
u64
),
32
*
sizeof
(
u64
));
if
(
!
ret
&&
copy_to_user
(
reg_window
,
window
,
sizeof
(
window
)))
return
-
EFAULT
;
}
if
(
!
ret
&&
count
>
0
)
{
unsigned
long
tstate
;
/* TSTATE */
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
tstate
,
32
*
sizeof
(
u64
),
33
*
sizeof
(
u64
));
if
(
!
ret
)
{
/* Only the condition codes can be modified
* in the %tstate register.
*/
tstate
&=
(
TSTATE_ICC
|
TSTATE_XCC
);
regs
->
tstate
&=
~
(
TSTATE_ICC
|
TSTATE_XCC
);
regs
->
tstate
|=
tstate
;
}
}
if
(
!
ret
)
{
/* TPC, TNPC */
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
regs
->
tpc
,
33
*
sizeof
(
u64
),
35
*
sizeof
(
u64
));
}
if
(
!
ret
)
{
unsigned
long
y
;
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
y
,
35
*
sizeof
(
u64
),
36
*
sizeof
(
u64
));
if
(
!
ret
)
regs
->
y
=
y
;
}
if
(
!
ret
)
ret
=
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
36
*
sizeof
(
u64
),
-
1
);
return
ret
;
}
static
int
fpregs64_get
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
void
*
kbuf
,
void
__user
*
ubuf
)
{
const
unsigned
long
*
fpregs
=
task_thread_info
(
target
)
->
fpregs
;
unsigned
long
fprs
,
fsr
,
gsr
;
int
ret
;
if
(
target
==
current
)
save_and_clear_fpu
();
fprs
=
task_thread_info
(
target
)
->
fpsaved
[
0
];
if
(
fprs
&
FPRS_DL
)
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
fpregs
,
0
,
16
*
sizeof
(
u64
));
else
ret
=
user_regset_copyout_zero
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
0
,
16
*
sizeof
(
u64
));
if
(
!
ret
)
{
if
(
fprs
&
FPRS_DU
)
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
fpregs
+
16
,
16
*
sizeof
(
u64
),
32
*
sizeof
(
u64
));
else
ret
=
user_regset_copyout_zero
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
16
*
sizeof
(
u64
),
32
*
sizeof
(
u64
));
}
if
(
fprs
&
FPRS_FEF
)
{
fsr
=
task_thread_info
(
target
)
->
xfsr
[
0
];
gsr
=
task_thread_info
(
target
)
->
gsr
[
0
];
}
else
{
fsr
=
gsr
=
0
;
}
if
(
!
ret
)
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
fsr
,
32
*
sizeof
(
u64
),
33
*
sizeof
(
u64
));
if
(
!
ret
)
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
gsr
,
33
*
sizeof
(
u64
),
34
*
sizeof
(
u64
));
if
(
!
ret
)
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
fprs
,
34
*
sizeof
(
u64
),
35
*
sizeof
(
u64
));
if
(
!
ret
)
ret
=
user_regset_copyout_zero
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
35
*
sizeof
(
u64
),
-
1
);
return
ret
;
}
static
int
fpregs64_set
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
const
void
*
kbuf
,
const
void
__user
*
ubuf
)
{
unsigned
long
*
fpregs
=
task_thread_info
(
target
)
->
fpregs
;
unsigned
long
fprs
;
int
ret
;
if
(
target
==
current
)
save_and_clear_fpu
();
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
fpregs
,
0
,
32
*
sizeof
(
u64
));
if
(
!
ret
)
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
task_thread_info
(
target
)
->
xfsr
,
32
*
sizeof
(
u64
),
33
*
sizeof
(
u64
));
if
(
!
ret
)
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
task_thread_info
(
target
)
->
gsr
,
33
*
sizeof
(
u64
),
34
*
sizeof
(
u64
));
fprs
=
task_thread_info
(
target
)
->
fpsaved
[
0
];
if
(
!
ret
&&
count
>
0
)
{
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
fprs
,
34
*
sizeof
(
u64
),
35
*
sizeof
(
u64
));
}
fprs
|=
(
FPRS_FEF
|
FPRS_DL
|
FPRS_DU
);
task_thread_info
(
target
)
->
fpsaved
[
0
]
=
fprs
;
if
(
!
ret
)
ret
=
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
35
*
sizeof
(
u64
),
-
1
);
return
ret
;
}
static
const
struct
user_regset
sparc64_regsets
[]
=
{
/* Format is:
* G0 --> G7
* O0 --> O7
* L0 --> L7
* I0 --> I7
* TSTATE, TPC, TNPC, Y
*/
[
REGSET_GENERAL
]
=
{
.
core_note_type
=
NT_PRSTATUS
,
.
n
=
36
*
sizeof
(
u64
),
.
size
=
sizeof
(
u64
),
.
align
=
sizeof
(
u64
),
.
get
=
genregs64_get
,
.
set
=
genregs64_set
},
/* Format is:
* F0 --> F63
* FSR
* GSR
* FPRS
*/
[
REGSET_FP
]
=
{
.
core_note_type
=
NT_PRFPREG
,
.
n
=
35
*
sizeof
(
u64
),
.
size
=
sizeof
(
u64
),
.
align
=
sizeof
(
u64
),
.
get
=
fpregs64_get
,
.
set
=
fpregs64_set
},
};
static
const
struct
user_regset_view
user_sparc64_view
=
{
.
name
=
"sparc64"
,
.
e_machine
=
EM_SPARCV9
,
.
regsets
=
sparc64_regsets
,
.
n
=
ARRAY_SIZE
(
sparc64_regsets
)
};
static
int
genregs32_get
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
void
*
kbuf
,
void
__user
*
ubuf
)
{
const
struct
pt_regs
*
regs
=
task_pt_regs
(
target
);
compat_ulong_t
__user
*
reg_window
;
compat_ulong_t
*
k
=
kbuf
;
compat_ulong_t
__user
*
u
=
ubuf
;
compat_ulong_t
reg
;
if
(
target
==
current
)
flushw_user
();
pos
/=
sizeof
(
reg
);
count
/=
sizeof
(
reg
);
if
(
kbuf
)
{
for
(;
count
>
0
&&
pos
<
16
;
count
--
)
*
k
++
=
regs
->
u_regs
[
pos
++
];
reg_window
=
(
compat_ulong_t
__user
*
)
regs
->
u_regs
[
UREG_I6
];
for
(;
count
>
0
&&
pos
<
32
;
count
--
)
{
if
(
get_user
(
*
k
++
,
&
reg_window
[
pos
++
]))
return
-
EFAULT
;
}
}
else
{
for
(;
count
>
0
&&
pos
<
16
;
count
--
)
{
if
(
put_user
((
compat_ulong_t
)
regs
->
u_regs
[
pos
++
],
u
++
))
return
-
EFAULT
;
}
reg_window
=
(
compat_ulong_t
__user
*
)
regs
->
u_regs
[
UREG_I6
];
for
(;
count
>
0
&&
pos
<
32
;
count
--
)
{
if
(
get_user
(
reg
,
&
reg_window
[
pos
++
])
||
put_user
(
reg
,
u
++
))
return
-
EFAULT
;
}
}
while
(
count
>
0
)
{
switch
(
pos
)
{
case
32
:
/* PSR */
reg
=
tstate_to_psr
(
regs
->
tstate
);
break
;
case
33
:
/* PC */
reg
=
regs
->
tpc
;
break
;
case
34
:
/* NPC */
reg
=
regs
->
tnpc
;
break
;
case
35
:
/* Y */
reg
=
regs
->
y
;
break
;
case
36
:
/* WIM */
case
37
:
/* TBR */
reg
=
0
;
break
;
default:
goto
finish
;
}
if
(
kbuf
)
*
k
++
=
reg
;
else
if
(
put_user
(
reg
,
u
++
))
return
-
EFAULT
;
pos
++
;
count
--
;
}
finish:
pos
*=
sizeof
(
reg
);
count
*=
sizeof
(
reg
);
return
user_regset_copyout_zero
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
38
*
sizeof
(
reg
),
-
1
);
}
static
int
genregs32_set
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
const
void
*
kbuf
,
const
void
__user
*
ubuf
)
{
struct
pt_regs
*
regs
=
task_pt_regs
(
target
);
compat_ulong_t
__user
*
reg_window
;
const
compat_ulong_t
*
k
=
kbuf
;
const
compat_ulong_t
__user
*
u
=
ubuf
;
compat_ulong_t
reg
;
if
(
target
==
current
)
flushw_user
();
pos
/=
sizeof
(
reg
);
count
/=
sizeof
(
reg
);
if
(
kbuf
)
{
for
(;
count
>
0
&&
pos
<
16
;
count
--
)
regs
->
u_regs
[
pos
++
]
=
*
k
++
;
reg_window
=
(
compat_ulong_t
__user
*
)
regs
->
u_regs
[
UREG_I6
];
for
(;
count
>
0
&&
pos
<
32
;
count
--
)
{
if
(
put_user
(
*
k
++
,
&
reg_window
[
pos
++
]))
return
-
EFAULT
;
}
}
else
{
for
(;
count
>
0
&&
pos
<
16
;
count
--
)
{
if
(
get_user
(
reg
,
u
++
))
return
-
EFAULT
;
regs
->
u_regs
[
pos
++
]
=
reg
;
}
reg_window
=
(
compat_ulong_t
__user
*
)
regs
->
u_regs
[
UREG_I6
];
for
(;
count
>
0
&&
pos
<
32
;
count
--
)
{
if
(
get_user
(
reg
,
u
++
)
||
put_user
(
reg
,
&
reg_window
[
pos
++
]))
return
-
EFAULT
;
}
}
while
(
count
>
0
)
{
unsigned
long
tstate
;
if
(
kbuf
)
reg
=
*
k
++
;
else
if
(
get_user
(
reg
,
u
++
))
return
-
EFAULT
;
switch
(
pos
)
{
case
32
:
/* PSR */
tstate
=
regs
->
tstate
;
tstate
&=
~
(
TSTATE_ICC
|
TSTATE_XCC
);
tstate
|=
psr_to_tstate_icc
(
reg
);
regs
->
tstate
=
tstate
;
break
;
case
33
:
/* PC */
regs
->
tpc
=
reg
;
break
;
case
34
:
/* NPC */
regs
->
tnpc
=
reg
;
break
;
case
35
:
/* Y */
regs
->
y
=
reg
;
break
;
case
36
:
/* WIM */
case
37
:
/* TBR */
break
;
default:
goto
finish
;
}
pos
++
;
count
--
;
}
finish:
pos
*=
sizeof
(
reg
);
count
*=
sizeof
(
reg
);
return
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
38
*
sizeof
(
reg
),
-
1
);
}
static
int
fpregs32_get
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
void
*
kbuf
,
void
__user
*
ubuf
)
{
const
unsigned
long
*
fpregs
=
task_thread_info
(
target
)
->
fpregs
;
compat_ulong_t
enabled
;
unsigned
long
fprs
;
compat_ulong_t
fsr
;
int
ret
=
0
;
if
(
target
==
current
)
save_and_clear_fpu
();
fprs
=
task_thread_info
(
target
)
->
fpsaved
[
0
];
if
(
fprs
&
FPRS_FEF
)
{
fsr
=
task_thread_info
(
target
)
->
xfsr
[
0
];
enabled
=
1
;
}
else
{
fsr
=
0
;
enabled
=
0
;
}
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
fpregs
,
0
,
32
*
sizeof
(
u32
));
if
(
!
ret
)
ret
=
user_regset_copyout_zero
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
if
(
!
ret
)
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
fsr
,
33
*
sizeof
(
u32
),
34
*
sizeof
(
u32
));
if
(
!
ret
)
{
compat_ulong_t
val
;
val
=
(
enabled
<<
8
)
|
(
8
<<
16
);
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
val
,
34
*
sizeof
(
u32
),
35
*
sizeof
(
u32
));
}
if
(
!
ret
)
ret
=
user_regset_copyout_zero
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
35
*
sizeof
(
u32
),
-
1
);
return
ret
;
}
static
int
fpregs32_set
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
const
void
*
kbuf
,
const
void
__user
*
ubuf
)
{
unsigned
long
*
fpregs
=
task_thread_info
(
target
)
->
fpregs
;
unsigned
long
fprs
;
int
ret
;
if
(
target
==
current
)
save_and_clear_fpu
();
fprs
=
task_thread_info
(
target
)
->
fpsaved
[
0
];
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
fpregs
,
0
,
32
*
sizeof
(
u32
));
if
(
!
ret
)
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
if
(
!
ret
&&
count
>
0
)
{
compat_ulong_t
fsr
;
unsigned
long
val
;
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
fsr
,
33
*
sizeof
(
u32
),
34
*
sizeof
(
u32
));
if
(
!
ret
)
{
val
=
task_thread_info
(
target
)
->
xfsr
[
0
];
val
&=
0xffffffff00000000UL
;
val
|=
fsr
;
task_thread_info
(
target
)
->
xfsr
[
0
]
=
val
;
}
}
fprs
|=
(
FPRS_FEF
|
FPRS_DL
);
task_thread_info
(
target
)
->
fpsaved
[
0
]
=
fprs
;
if
(
!
ret
)
ret
=
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
34
*
sizeof
(
u32
),
-
1
);
return
ret
;
}
static
const
struct
user_regset
sparc32_regsets
[]
=
{
/* Format is:
* G0 --> G7
* O0 --> O7
* L0 --> L7
* I0 --> I7
* PSR, PC, nPC, Y, WIM, TBR
*/
[
REGSET_GENERAL
]
=
{
.
core_note_type
=
NT_PRSTATUS
,
.
n
=
38
*
sizeof
(
u32
),
.
size
=
sizeof
(
u32
),
.
align
=
sizeof
(
u32
),
.
get
=
genregs32_get
,
.
set
=
genregs32_set
},
/* Format is:
* F0 --> F31
* empty 32-bit word
* FSR (32--bit word)
* FPU QUEUE COUNT (8-bit char)
* FPU QUEUE ENTRYSIZE (8-bit char)
* FPU ENABLED (8-bit char)
* empty 8-bit char
* FPU QUEUE (64 32-bit ints)
*/
[
REGSET_FP
]
=
{
.
core_note_type
=
NT_PRFPREG
,
.
n
=
99
*
sizeof
(
u32
),
.
size
=
sizeof
(
u32
),
.
align
=
sizeof
(
u32
),
.
get
=
fpregs32_get
,
.
set
=
fpregs32_set
},
};
static
const
struct
user_regset_view
user_sparc32_view
=
{
.
name
=
"sparc"
,
.
e_machine
=
EM_SPARC
,
.
regsets
=
sparc32_regsets
,
.
n
=
ARRAY_SIZE
(
sparc32_regsets
)
};
const
struct
user_regset_view
*
task_user_regset_view
(
struct
task_struct
*
task
)
{
if
(
test_tsk_thread_flag
(
task
,
TIF_32BIT
))
return
&
user_sparc32_view
;
return
&
user_sparc64_view
;
}
asmlinkage
void
do_ptrace
(
struct
pt_regs
*
regs
)
{
int
request
=
regs
->
u_regs
[
UREG_I0
];
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录