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
1e56f6d2
Commit
1e56f6d2
authored
Jul 27, 2020
by
Al Viro
Browse files
Options
Browse Files
Download
Plain Diff
Merge branches 'regset.x86', 'regset.ia64', 'regset.sparc' and 'regset.arm64' into work.regset
parents
b4e9c954
4dfa103e
e3fdfa37
b7e46c52
d547175b
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
588 additions
and
410 deletions
+588
-410
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/ptrace.c
+38
-29
arch/ia64/kernel/ptrace.c
arch/ia64/kernel/ptrace.c
+98
-177
arch/sparc/kernel/ptrace_32.c
arch/sparc/kernel/ptrace_32.c
+155
-71
arch/sparc/kernel/ptrace_64.c
arch/sparc/kernel/ptrace_64.c
+291
-110
arch/x86/include/asm/fpu/internal.h
arch/x86/include/asm/fpu/internal.h
+0
-1
arch/x86/kernel/fpu/regset.c
arch/x86/kernel/fpu/regset.c
+0
-16
arch/x86/kernel/fpu/signal.c
arch/x86/kernel/fpu/signal.c
+6
-6
No files found.
arch/arm64/kernel/ptrace.c
View file @
1e56f6d2
...
...
@@ -1237,6 +1237,22 @@ enum compat_regset {
REGSET_COMPAT_VFP
,
};
static
inline
compat_ulong_t
compat_get_user_reg
(
struct
task_struct
*
task
,
int
idx
)
{
struct
pt_regs
*
regs
=
task_pt_regs
(
task
);
switch
(
idx
)
{
case
15
:
return
regs
->
pc
;
case
16
:
return
pstate_to_compat_psr
(
regs
->
pstate
);
case
17
:
return
regs
->
orig_x0
;
default:
return
regs
->
regs
[
idx
];
}
}
static
int
compat_gpr_get
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
...
...
@@ -1255,23 +1271,7 @@ static int compat_gpr_get(struct task_struct *target,
return
-
EIO
;
for
(
i
=
0
;
i
<
num_regs
;
++
i
)
{
unsigned
int
idx
=
start
+
i
;
compat_ulong_t
reg
;
switch
(
idx
)
{
case
15
:
reg
=
task_pt_regs
(
target
)
->
pc
;
break
;
case
16
:
reg
=
task_pt_regs
(
target
)
->
pstate
;
reg
=
pstate_to_compat_psr
(
reg
);
break
;
case
17
:
reg
=
task_pt_regs
(
target
)
->
orig_x0
;
break
;
default:
reg
=
task_pt_regs
(
target
)
->
regs
[
idx
];
}
compat_ulong_t
reg
=
compat_get_user_reg
(
target
,
start
+
i
);
if
(
kbuf
)
{
memcpy
(
kbuf
,
&
reg
,
sizeof
(
reg
));
...
...
@@ -1541,9 +1541,7 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
else
if
(
off
==
COMPAT_PT_TEXT_END_ADDR
)
tmp
=
tsk
->
mm
->
end_code
;
else
if
(
off
<
sizeof
(
compat_elf_gregset_t
))
return
copy_regset_to_user
(
tsk
,
&
user_aarch32_view
,
REGSET_COMPAT_GPR
,
off
,
sizeof
(
compat_ulong_t
),
ret
);
tmp
=
compat_get_user_reg
(
tsk
,
off
>>
2
);
else
if
(
off
>=
COMPAT_USER_SZ
)
return
-
EIO
;
else
...
...
@@ -1555,8 +1553,8 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
static
int
compat_ptrace_write_user
(
struct
task_struct
*
tsk
,
compat_ulong_t
off
,
compat_ulong_t
val
)
{
int
ret
;
mm_segment_t
old_fs
=
get_fs
()
;
struct
pt_regs
newregs
=
*
task_pt_regs
(
tsk
)
;
unsigned
int
idx
=
off
/
4
;
if
(
off
&
3
||
off
>=
COMPAT_USER_SZ
)
return
-
EIO
;
...
...
@@ -1564,14 +1562,25 @@ static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
if
(
off
>=
sizeof
(
compat_elf_gregset_t
))
return
0
;
set_fs
(
KERNEL_DS
);
ret
=
copy_regset_from_user
(
tsk
,
&
user_aarch32_view
,
REGSET_COMPAT_GPR
,
off
,
sizeof
(
compat_ulong_t
),
&
val
);
set_fs
(
old_fs
);
switch
(
idx
)
{
case
15
:
newregs
.
pc
=
val
;
break
;
case
16
:
newregs
.
pstate
=
compat_psr_to_pstate
(
val
);
break
;
case
17
:
newregs
.
orig_x0
=
val
;
break
;
default:
newregs
.
regs
[
idx
]
=
val
;
}
if
(
!
valid_user_regs
(
&
newregs
.
user_regs
,
tsk
))
return
-
EINVAL
;
return
ret
;
*
task_pt_regs
(
tsk
)
=
newregs
;
return
0
;
}
#ifdef CONFIG_HAVE_HW_BREAKPOINT
...
...
arch/ia64/kernel/ptrace.c
View file @
1e56f6d2
This diff is collapsed.
Click to expand it.
arch/sparc/kernel/ptrace_32.c
View file @
1e56f6d2
...
...
@@ -99,15 +99,13 @@ static int genregs32_get(struct task_struct *target,
if
(
ret
||
!
count
)
return
ret
;
if
(
pos
<
32
*
sizeof
(
u32
))
{
if
(
regwindow32_get
(
target
,
regs
,
uregs
))
return
-
EFAULT
;
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
uregs
,
16
*
sizeof
(
u32
),
32
*
sizeof
(
u32
));
if
(
ret
||
!
count
)
return
ret
;
}
if
(
regwindow32_get
(
target
,
regs
,
uregs
))
return
-
EFAULT
;
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
uregs
,
16
*
sizeof
(
u32
),
32
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
uregs
[
0
]
=
regs
->
psr
;
uregs
[
1
]
=
regs
->
pc
;
...
...
@@ -139,19 +137,18 @@ static int genregs32_set(struct task_struct *target,
if
(
ret
||
!
count
)
return
ret
;
if
(
pos
<
32
*
sizeof
(
u32
))
{
if
(
regwindow32_get
(
target
,
regs
,
uregs
))
return
-
EFAULT
;
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
uregs
,
16
*
sizeof
(
u32
),
32
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
if
(
regwindow32_set
(
target
,
regs
,
uregs
))
return
-
EFAULT
;
if
(
!
count
)
return
0
;
}
if
(
regwindow32_get
(
target
,
regs
,
uregs
))
return
-
EFAULT
;
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
uregs
,
16
*
sizeof
(
u32
),
32
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
if
(
regwindow32_set
(
target
,
regs
,
uregs
))
return
-
EFAULT
;
if
(
!
count
)
return
0
;
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
psr
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
...
...
@@ -243,13 +240,11 @@ static int fpregs32_set(struct task_struct *target,
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
if
(
!
ret
&&
count
>
0
)
{
if
(
!
ret
)
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
target
->
thread
.
fsr
,
33
*
sizeof
(
u32
),
34
*
sizeof
(
u32
));
}
if
(
!
ret
)
ret
=
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
34
*
sizeof
(
u32
),
-
1
);
...
...
@@ -288,6 +283,125 @@ static const struct user_regset sparc32_regsets[] = {
},
};
static
int
getregs_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
=
target
->
thread
.
kregs
;
u32
v
[
4
];
int
ret
;
if
(
target
==
current
)
flush_user_windows
();
v
[
0
]
=
regs
->
psr
;
v
[
1
]
=
regs
->
pc
;
v
[
2
]
=
regs
->
npc
;
v
[
3
]
=
regs
->
y
;
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
v
,
0
*
sizeof
(
u32
),
4
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
return
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
regs
->
u_regs
+
1
,
4
*
sizeof
(
u32
),
19
*
sizeof
(
u32
));
}
static
int
setregs_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
=
target
->
thread
.
kregs
;
u32
v
[
4
];
int
ret
;
if
(
target
==
current
)
flush_user_windows
();
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
v
,
0
,
4
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
regs
->
psr
=
(
regs
->
psr
&
~
(
PSR_ICC
|
PSR_SYSCALL
))
|
(
v
[
0
]
&
(
PSR_ICC
|
PSR_SYSCALL
));
regs
->
pc
=
v
[
1
];
regs
->
npc
=
v
[
2
];
regs
->
y
=
v
[
3
];
return
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
regs
->
u_regs
+
1
,
4
*
sizeof
(
u32
)
,
19
*
sizeof
(
u32
));
}
static
int
getfpregs_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
=
target
->
thread
.
float_regs
;
int
ret
=
0
;
#if 0
if (target == current)
save_and_clear_fpu();
#endif
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
fpregs
,
0
,
32
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
target
->
thread
.
fsr
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
return
user_regset_copyout_zero
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
33
*
sizeof
(
u32
),
68
*
sizeof
(
u32
));
}
static
int
setfpregs_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
=
target
->
thread
.
float_regs
;
int
ret
;
#if 0
if (target == current)
save_and_clear_fpu();
#endif
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
fpregs
,
0
,
32
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
return
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
target
->
thread
.
fsr
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
}
static
const
struct
user_regset
ptrace32_regsets
[]
=
{
[
REGSET_GENERAL
]
=
{
.
n
=
19
,
.
size
=
sizeof
(
u32
),
.
get
=
getregs_get
,
.
set
=
setregs_set
,
},
[
REGSET_FP
]
=
{
.
n
=
68
,
.
size
=
sizeof
(
u32
),
.
get
=
getfpregs_get
,
.
set
=
setfpregs_set
,
},
};
static
const
struct
user_regset_view
ptrace32_view
=
{
.
regsets
=
ptrace32_regsets
,
.
n
=
ARRAY_SIZE
(
ptrace32_regsets
)
};
static
const
struct
user_regset_view
user_sparc32_view
=
{
.
name
=
"sparc"
,
.
e_machine
=
EM_SPARC
,
.
regsets
=
sparc32_regsets
,
.
n
=
ARRAY_SIZE
(
sparc32_regsets
)
...
...
@@ -315,74 +429,44 @@ long arch_ptrace(struct task_struct *child, long request,
{
unsigned
long
addr2
=
current
->
thread
.
kregs
->
u_regs
[
UREG_I4
];
void
__user
*
addr2p
;
const
struct
user_regset_view
*
view
;
struct
pt_regs
__user
*
pregs
;
struct
fps
__user
*
fps
;
int
ret
;
view
=
task_user_regset_view
(
current
);
addr2p
=
(
void
__user
*
)
addr2
;
pregs
=
(
struct
pt_regs
__user
*
)
addr
;
fps
=
(
struct
fps
__user
*
)
addr
;
switch
(
request
)
{
case
PTRACE_GETREGS
:
{
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_GENERAL
,
32
*
sizeof
(
u32
),
4
*
sizeof
(
u32
),
&
pregs
->
psr
);
if
(
!
ret
)
copy_regset_to_user
(
child
,
view
,
REGSET_GENERAL
,
1
*
sizeof
(
u32
),
15
*
sizeof
(
u32
),
&
pregs
->
u_regs
[
0
]);
ret
=
copy_regset_to_user
(
child
,
&
ptrace32_view
,
REGSET_GENERAL
,
0
,
19
*
sizeof
(
u32
),
pregs
);
break
;
}
case
PTRACE_SETREGS
:
{
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_GENERAL
,
32
*
sizeof
(
u32
),
4
*
sizeof
(
u32
),
&
pregs
->
psr
);
if
(
!
ret
)
copy_regset_from_user
(
child
,
view
,
REGSET_GENERAL
,
1
*
sizeof
(
u32
),
15
*
sizeof
(
u32
),
&
pregs
->
u_regs
[
0
]);
ret
=
copy_regset_from_user
(
child
,
&
ptrace32_view
,
REGSET_GENERAL
,
0
,
19
*
sizeof
(
u32
),
pregs
);
break
;
}
case
PTRACE_GETFPREGS
:
{
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_FP
,
0
*
sizeof
(
u32
),
32
*
sizeof
(
u32
),
&
fps
->
regs
[
0
]);
if
(
!
ret
)
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_FP
,
33
*
sizeof
(
u32
),
1
*
sizeof
(
u32
),
&
fps
->
fsr
);
if
(
!
ret
)
{
if
(
__put_user
(
0
,
&
fps
->
fpqd
)
||
__put_user
(
0
,
&
fps
->
flags
)
||
__put_user
(
0
,
&
fps
->
extra
)
||
clear_user
(
fps
->
fpq
,
sizeof
(
fps
->
fpq
)))
ret
=
-
EFAULT
;
}
ret
=
copy_regset_to_user
(
child
,
&
ptrace32_view
,
REGSET_FP
,
0
,
68
*
sizeof
(
u32
),
fps
);
break
;
}
case
PTRACE_SETFPREGS
:
{
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_FP
,
0
*
sizeof
(
u32
),
32
*
sizeof
(
u32
),
&
fps
->
regs
[
0
]);
if
(
!
ret
)
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_FP
,
33
*
sizeof
(
u32
),
1
*
sizeof
(
u32
),
&
fps
->
fsr
);
ret
=
copy_regset_from_user
(
child
,
&
ptrace32_view
,
REGSET_FP
,
0
,
33
*
sizeof
(
u32
),
fps
);
break
;
}
...
...
arch/sparc/kernel/ptrace_64.c
View file @
1e56f6d2
This diff is collapsed.
Click to expand it.
arch/x86/include/asm/fpu/internal.h
View file @
1e56f6d2
...
...
@@ -34,7 +34,6 @@ extern int fpu__copy(struct task_struct *dst, struct task_struct *src);
extern
void
fpu__clear_user_states
(
struct
fpu
*
fpu
);
extern
void
fpu__clear_all
(
struct
fpu
*
fpu
);
extern
int
fpu__exception_code
(
struct
fpu
*
fpu
,
int
trap_nr
);
extern
int
dump_fpu
(
struct
pt_regs
*
ptregs
,
struct
user_i387_struct
*
fpstate
);
/*
* Boot time FPU initialization functions:
...
...
arch/x86/kernel/fpu/regset.c
View file @
1e56f6d2
...
...
@@ -356,20 +356,4 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
return
ret
;
}
/*
* FPU state for core dumps.
* This is only used for a.out dumps now.
* It is declared generically using elf_fpregset_t (which is
* struct user_i387_struct) but is in fact only used for 32-bit
* dumps, so on 64-bit it is really struct user_i387_ia32_struct.
*/
int
dump_fpu
(
struct
pt_regs
*
regs
,
struct
user_i387_struct
*
ufpu
)
{
struct
task_struct
*
tsk
=
current
;
return
!
fpregs_get
(
tsk
,
NULL
,
0
,
sizeof
(
struct
user_i387_ia32_struct
),
ufpu
,
NULL
);
}
EXPORT_SYMBOL
(
dump_fpu
);
#endif
/* CONFIG_X86_32 || CONFIG_IA32_EMULATION */
arch/x86/kernel/fpu/signal.c
View file @
1e56f6d2
...
...
@@ -170,14 +170,14 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
ia32_fxstate
&=
(
IS_ENABLED
(
CONFIG_X86_32
)
||
IS_ENABLED
(
CONFIG_IA32_EMULATION
));
if
(
!
static_cpu_has
(
X86_FEATURE_FPU
))
{
struct
user_i387_ia32_struct
fp
;
fpregs_soft_get
(
current
,
NULL
,
0
,
sizeof
(
fp
),
&
fp
,
NULL
);
return
copy_to_user
(
buf
,
&
fp
,
sizeof
(
fp
))
?
-
EFAULT
:
0
;
}
if
(
!
access_ok
(
buf
,
size
))
return
-
EACCES
;
if
(
!
static_cpu_has
(
X86_FEATURE_FPU
))
return
fpregs_soft_get
(
current
,
NULL
,
0
,
sizeof
(
struct
user_i387_ia32_struct
),
NULL
,
(
struct
_fpstate_32
__user
*
)
buf
)
?
-
1
:
1
;
retry:
/*
* Load the FPU registers if they are not valid for the current task.
...
...
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