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
650da250
Commit
650da250
authored
Oct 09, 2017
by
Christian Borntraeger
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'sthyi' of
git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
into kvms390/next
get sthyi rework with the KVM changes
parents
2bd6bf03
3d8757b8
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
182 additions
and
71 deletions
+182
-71
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/kvm_host.h
+0
-1
arch/s390/include/asm/sysinfo.h
arch/s390/include/asm/sysinfo.h
+1
-0
arch/s390/include/uapi/asm/sthyi.h
arch/s390/include/uapi/asm/sthyi.h
+6
-0
arch/s390/include/uapi/asm/unistd.h
arch/s390/include/uapi/asm/unistd.h
+2
-1
arch/s390/kernel/Makefile
arch/s390/kernel/Makefile
+1
-1
arch/s390/kernel/compat_wrapper.c
arch/s390/kernel/compat_wrapper.c
+1
-0
arch/s390/kernel/entry.h
arch/s390/kernel/entry.h
+1
-0
arch/s390/kernel/sthyi.c
arch/s390/kernel/sthyi.c
+110
-62
arch/s390/kernel/syscalls.S
arch/s390/kernel/syscalls.S
+1
-0
arch/s390/kvm/Makefile
arch/s390/kvm/Makefile
+1
-1
arch/s390/kvm/intercept.c
arch/s390/kvm/intercept.c
+56
-0
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.c
+0
-2
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/kvm-s390.h
+2
-3
No files found.
arch/s390/include/asm/kvm_host.h
View file @
650da250
...
...
@@ -736,7 +736,6 @@ struct kvm_arch{
wait_queue_head_t
ipte_wq
;
int
ipte_lock_count
;
struct
mutex
ipte_mutex
;
struct
ratelimit_state
sthyi_limit
;
spinlock_t
start_stop_lock
;
struct
sie_page2
*
sie_page2
;
struct
kvm_s390_cpu_model
model
;
...
...
arch/s390/include/asm/sysinfo.h
View file @
650da250
...
...
@@ -198,4 +198,5 @@ struct service_level {
int
register_service_level
(
struct
service_level
*
);
int
unregister_service_level
(
struct
service_level
*
);
int
sthyi_fill
(
void
*
dst
,
u64
*
rc
);
#endif
/* __ASM_S390_SYSINFO_H */
arch/s390/include/uapi/asm/sthyi.h
0 → 100644
View file @
650da250
#ifndef _UAPI_ASM_STHYI_H
#define _UAPI_ASM_STHYI_H
#define STHYI_FC_CP_IFL_CAP 0
#endif
/* _UAPI_ASM_STHYI_H */
arch/s390/include/uapi/asm/unistd.h
View file @
650da250
...
...
@@ -315,7 +315,8 @@
#define __NR_pwritev2 377
#define __NR_s390_guarded_storage 378
#define __NR_statx 379
#define NR_syscalls 380
#define __NR_s390_sthyi 380
#define NR_syscalls 381
/*
* There are some system calls that are not present on 64 bit, some
...
...
arch/s390/kernel/Makefile
View file @
650da250
...
...
@@ -55,7 +55,7 @@ obj-y := traps.o time.o process.o base.o early.o setup.o idle.o vtime.o
obj-y
+=
processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
obj-y
+=
debug.o irq.o ipl.o dis.o diag.o vdso.o als.o
obj-y
+=
sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
obj-y
+=
runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o
obj-y
+=
runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o
sthyi.o
obj-y
+=
entry.o reipl.o relocate_kernel.o kdebugfs.o
extra-y
+=
head.o head64.o vmlinux.lds
...
...
arch/s390/kernel/compat_wrapper.c
View file @
650da250
...
...
@@ -180,3 +180,4 @@ COMPAT_SYSCALL_WRAP3(mlock2, unsigned long, start, size_t, len, int, flags);
COMPAT_SYSCALL_WRAP6
(
copy_file_range
,
int
,
fd_in
,
loff_t
__user
*
,
off_in
,
int
,
fd_out
,
loff_t
__user
*
,
off_out
,
size_t
,
len
,
unsigned
int
,
flags
);
COMPAT_SYSCALL_WRAP2
(
s390_guarded_storage
,
int
,
command
,
struct
gs_cb
*
,
gs_cb
);
COMPAT_SYSCALL_WRAP5
(
statx
,
int
,
dfd
,
const
char
__user
*
,
path
,
unsigned
,
flags
,
unsigned
,
mask
,
struct
statx
__user
*
,
buffer
);
COMPAT_SYSCALL_WRAP4
(
s390_sthyi
,
unsigned
long
,
code
,
void
__user
*
,
info
,
u64
__user
*
,
rc
,
unsigned
long
,
flags
);
arch/s390/kernel/entry.h
View file @
650da250
...
...
@@ -77,6 +77,7 @@ long sys_s390_runtime_instr(int command, int signum);
long
sys_s390_guarded_storage
(
int
command
,
struct
gs_cb
__user
*
);
long
sys_s390_pci_mmio_write
(
unsigned
long
,
const
void
__user
*
,
size_t
);
long
sys_s390_pci_mmio_read
(
unsigned
long
,
void
__user
*
,
size_t
);
long
sys_s390_sthyi
(
unsigned
long
function_code
,
void
__user
*
buffer
,
u64
__user
*
return_code
,
unsigned
long
flags
);
DECLARE_PER_CPU
(
u64
,
mt_cycles
[
8
]);
...
...
arch/s390/k
vm
/sthyi.c
→
arch/s390/k
ernel
/sthyi.c
View file @
650da250
...
...
@@ -8,22 +8,19 @@
* Copyright IBM Corp. 2016
* Author(s): Janosch Frank <frankja@linux.vnet.ibm.com>
*/
#include <linux/kvm_host.h>
#include <linux/errno.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
#include <linux/ratelimit.h>
#include <asm/kvm_host.h>
#include <linux/syscalls.h>
#include <linux/mutex.h>
#include <asm/asm-offsets.h>
#include <asm/sclp.h>
#include <asm/diag.h>
#include <asm/sysinfo.h>
#include <asm/ebcdic.h>
#include "kvm-s390.h"
#include "gaccess.h"
#include "trace.h"
#include <asm/facility.h>
#include <asm/sthyi.h>
#include "entry.h"
#define DED_WEIGHT 0xffff
/*
...
...
@@ -144,6 +141,21 @@ struct lpar_cpu_inf {
struct
cpu_inf
ifl
;
};
/*
* STHYI requires extensive locking in the higher hypervisors
* and is very computational/memory expensive. Therefore we
* cache the retrieved data whose valid period is 1s.
*/
#define CACHE_VALID_JIFFIES HZ
struct
sthyi_info
{
void
*
info
;
unsigned
long
end
;
};
static
DEFINE_MUTEX
(
sthyi_mutex
);
static
struct
sthyi_info
sthyi_cache
;
static
inline
u64
cpu_id
(
u8
ctidx
,
void
*
diag224_buf
)
{
return
*
((
u64
*
)(
diag224_buf
+
(
ctidx
+
1
)
*
DIAG204_CPU_NAME_LEN
));
...
...
@@ -382,88 +394,124 @@ static void fill_diag(struct sthyi_sctns *sctns)
vfree
(
diag204_buf
);
}
static
int
sthyi
(
u64
vaddr
)
static
int
sthyi
(
u64
vaddr
,
u64
*
rc
)
{
register
u64
code
asm
(
"0"
)
=
0
;
register
u64
addr
asm
(
"2"
)
=
vaddr
;
register
u64
rcode
asm
(
"3"
);
int
cc
;
asm
volatile
(
".insn rre,0xB2560000,%[code],%[addr]
\n
"
"ipm %[cc]
\n
"
"srl %[cc],28
\n
"
:
[
cc
]
"=d"
(
cc
)
:
[
cc
]
"=d"
(
cc
)
,
"=d"
(
rcode
)
:
[
code
]
"d"
(
code
),
[
addr
]
"a"
(
addr
)
:
"3"
,
"memory"
,
"cc"
);
:
"memory"
,
"cc"
);
*
rc
=
rcode
;
return
cc
;
}
int
handle_sthyi
(
struct
kvm_vcpu
*
vcpu
)
static
int
fill_dst
(
void
*
dst
,
u64
*
rc
)
{
int
reg1
,
reg2
,
r
=
0
;
u64
code
,
addr
,
cc
=
0
;
struct
sthyi_sctns
*
sctns
=
NULL
;
if
(
!
test_kvm_facility
(
vcpu
->
kvm
,
74
))
return
kvm_s390_inject_program_int
(
vcpu
,
PGM_OPERATION
);
struct
sthyi_sctns
*
sctns
=
(
struct
sthyi_sctns
*
)
dst
;
/*
* STHYI requires extensive locking in the higher hypervisors
* and is very computational/memory expensive. Therefore we
* ratelimit the executions per VM.
* If the facility is on, we don't want to emulate the instruction.
* We ask the hypervisor to provide the data.
*/
if
(
!
__ratelimit
(
&
vcpu
->
kvm
->
arch
.
sthyi_limit
))
{
kvm_s390_retry_instr
(
vcpu
);
if
(
test_facility
(
74
))
return
sthyi
((
u64
)
dst
,
rc
);
fill_hdr
(
sctns
);
fill_stsi
(
sctns
);
fill_diag
(
sctns
);
*
rc
=
0
;
return
0
;
}
static
int
sthyi_init_cache
(
void
)
{
if
(
sthyi_cache
.
info
)
return
0
;
}
sthyi_cache
.
info
=
(
void
*
)
get_zeroed_page
(
GFP_KERNEL
);
if
(
!
sthyi_cache
.
info
)
return
-
ENOMEM
;
sthyi_cache
.
end
=
jiffies
-
1
;
/* expired */
return
0
;
}
kvm_s390_get_regs_rre
(
vcpu
,
&
reg1
,
&
reg2
);
code
=
vcpu
->
run
->
s
.
regs
.
gprs
[
reg1
];
addr
=
vcpu
->
run
->
s
.
regs
.
gprs
[
reg2
]
;
static
int
sthyi_update_cache
(
u64
*
rc
)
{
int
r
;
vcpu
->
stat
.
instruction_sthyi
++
;
VCPU_EVENT
(
vcpu
,
3
,
"STHYI: fc: %llu addr: 0x%016llx"
,
code
,
addr
);
trace_kvm_s390_handle_sthyi
(
vcpu
,
code
,
addr
);
memset
(
sthyi_cache
.
info
,
0
,
PAGE_SIZE
);
r
=
fill_dst
(
sthyi_cache
.
info
,
rc
);
if
(
r
)
return
r
;
sthyi_cache
.
end
=
jiffies
+
CACHE_VALID_JIFFIES
;
return
r
;
}
if
(
reg1
==
reg2
||
reg1
&
1
||
reg2
&
1
)
return
kvm_s390_inject_program_int
(
vcpu
,
PGM_SPECIFICATION
);
/*
* sthyi_fill - Fill page with data returned by the STHYI instruction
*
* @dst: Pointer to zeroed page
* @rc: Pointer for storing the return code of the instruction
*
* Fills the destination with system information returned by the STHYI
* instruction. The data is generated by emulation or execution of STHYI,
* if available. The return value is the condition code that would be
* returned, the rc parameter is the return code which is passed in
* register R2 + 1.
*/
int
sthyi_fill
(
void
*
dst
,
u64
*
rc
)
{
int
r
;
if
(
code
&
0xffff
)
{
cc
=
3
;
mutex_lock
(
&
sthyi_mutex
);
r
=
sthyi_init_cache
();
if
(
r
)
goto
out
;
}
if
(
addr
&
~
PAGE_MASK
)
return
kvm_s390_inject_program_int
(
vcpu
,
PGM_SPECIFICATION
);
if
(
time_is_before_jiffies
(
sthyi_cache
.
end
))
{
/* cache expired */
r
=
sthyi_update_cache
(
rc
);
if
(
r
)
goto
out
;
}
*
rc
=
0
;
memcpy
(
dst
,
sthyi_cache
.
info
,
PAGE_SIZE
);
out:
mutex_unlock
(
&
sthyi_mutex
);
return
r
;
}
EXPORT_SYMBOL_GPL
(
sthyi_fill
);
sctns
=
(
void
*
)
get_zeroed_page
(
GFP_KERNEL
);
if
(
!
sctns
)
SYSCALL_DEFINE4
(
s390_sthyi
,
unsigned
long
,
function_code
,
void
__user
*
,
buffer
,
u64
__user
*
,
return_code
,
unsigned
long
,
flags
)
{
u64
sthyi_rc
;
void
*
info
;
int
r
;
if
(
flags
)
return
-
EINVAL
;
if
(
function_code
!=
STHYI_FC_CP_IFL_CAP
)
return
-
EOPNOTSUPP
;
info
=
(
void
*
)
get_zeroed_page
(
GFP_KERNEL
);
if
(
!
info
)
return
-
ENOMEM
;
/*
* If we are a guest, we don't want to emulate an emulated
* instruction. We ask the hypervisor to provide the data.
*/
if
(
test_facility
(
74
))
{
cc
=
sthyi
((
u64
)
sctns
);
r
=
sthyi_fill
(
info
,
&
sthyi_rc
);
if
(
r
<
0
)
goto
out
;
if
(
return_code
&&
put_user
(
sthyi_rc
,
return_code
))
{
r
=
-
EFAULT
;
goto
out
;
}
fill_hdr
(
sctns
);
fill_stsi
(
sctns
);
fill_diag
(
sctns
);
if
(
copy_to_user
(
buffer
,
info
,
PAGE_SIZE
))
r
=
-
EFAULT
;
out:
if
(
!
cc
)
{
r
=
write_guest
(
vcpu
,
addr
,
reg2
,
sctns
,
PAGE_SIZE
);
if
(
r
)
{
free_page
((
unsigned
long
)
sctns
);
return
kvm_s390_inject_prog_cond
(
vcpu
,
r
);
}
}
free_page
((
unsigned
long
)
sctns
);
vcpu
->
run
->
s
.
regs
.
gprs
[
reg2
+
1
]
=
cc
?
4
:
0
;
kvm_s390_set_psw_cc
(
vcpu
,
cc
);
free_page
((
unsigned
long
)
info
);
return
r
;
}
arch/s390/kernel/syscalls.S
View file @
650da250
...
...
@@ -388,3 +388,4 @@ SYSCALL(sys_preadv2,compat_sys_preadv2)
SYSCALL
(
sys_pwritev2
,
compat_sys_pwritev2
)
SYSCALL
(
sys_s390_guarded_storage
,
compat_sys_s390_guarded_storage
)
/
*
378
*/
SYSCALL
(
sys_statx
,
compat_sys_statx
)
SYSCALL
(
sys_s390_sthyi
,
compat_sys_s390_sthyi
)
arch/s390/kvm/Makefile
View file @
650da250
...
...
@@ -12,6 +12,6 @@ common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o $(KVM)/irqch
ccflags-y
:=
-Ivirt
/kvm
-Iarch
/s390/kvm
kvm-objs
:=
$
(
common-objs
)
kvm-s390.o intercept.o interrupt.o priv.o sigp.o
kvm-objs
+=
diag.o gaccess.o guestdbg.o
sthyi.o
vsie.o
kvm-objs
+=
diag.o gaccess.o guestdbg.o vsie.o
obj-$(CONFIG_KVM)
+=
kvm.o
arch/s390/kvm/intercept.c
View file @
650da250
...
...
@@ -18,6 +18,7 @@
#include <asm/kvm_host.h>
#include <asm/asm-offsets.h>
#include <asm/irq.h>
#include <asm/sysinfo.h>
#include "kvm-s390.h"
#include "gaccess.h"
...
...
@@ -360,6 +361,61 @@ static int handle_partial_execution(struct kvm_vcpu *vcpu)
return
-
EOPNOTSUPP
;
}
/*
* Handle the sthyi instruction that provides the guest with system
* information, like current CPU resources available at each level of
* the machine.
*/
int
handle_sthyi
(
struct
kvm_vcpu
*
vcpu
)
{
int
reg1
,
reg2
,
r
=
0
;
u64
code
,
addr
,
cc
=
0
,
rc
=
0
;
struct
sthyi_sctns
*
sctns
=
NULL
;
if
(
!
test_kvm_facility
(
vcpu
->
kvm
,
74
))
return
kvm_s390_inject_program_int
(
vcpu
,
PGM_OPERATION
);
kvm_s390_get_regs_rre
(
vcpu
,
&
reg1
,
&
reg2
);
code
=
vcpu
->
run
->
s
.
regs
.
gprs
[
reg1
];
addr
=
vcpu
->
run
->
s
.
regs
.
gprs
[
reg2
];
vcpu
->
stat
.
instruction_sthyi
++
;
VCPU_EVENT
(
vcpu
,
3
,
"STHYI: fc: %llu addr: 0x%016llx"
,
code
,
addr
);
trace_kvm_s390_handle_sthyi
(
vcpu
,
code
,
addr
);
if
(
reg1
==
reg2
||
reg1
&
1
||
reg2
&
1
)
return
kvm_s390_inject_program_int
(
vcpu
,
PGM_SPECIFICATION
);
if
(
code
&
0xffff
)
{
cc
=
3
;
rc
=
4
;
goto
out
;
}
if
(
addr
&
~
PAGE_MASK
)
return
kvm_s390_inject_program_int
(
vcpu
,
PGM_SPECIFICATION
);
sctns
=
(
void
*
)
get_zeroed_page
(
GFP_KERNEL
);
if
(
!
sctns
)
return
-
ENOMEM
;
cc
=
sthyi_fill
(
sctns
,
&
rc
);
out:
if
(
!
cc
)
{
r
=
write_guest
(
vcpu
,
addr
,
reg2
,
sctns
,
PAGE_SIZE
);
if
(
r
)
{
free_page
((
unsigned
long
)
sctns
);
return
kvm_s390_inject_prog_cond
(
vcpu
,
r
);
}
}
free_page
((
unsigned
long
)
sctns
);
vcpu
->
run
->
s
.
regs
.
gprs
[
reg2
+
1
]
=
rc
;
kvm_s390_set_psw_cc
(
vcpu
,
cc
);
return
r
;
}
static
int
handle_operexc
(
struct
kvm_vcpu
*
vcpu
)
{
psw_t
oldpsw
,
newpsw
;
...
...
arch/s390/kvm/kvm-s390.c
View file @
650da250
...
...
@@ -1884,8 +1884,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
rc
=
-
ENOMEM
;
ratelimit_state_init
(
&
kvm
->
arch
.
sthyi_limit
,
5
*
HZ
,
500
);
kvm
->
arch
.
use_esca
=
0
;
/* start with basic SCA */
if
(
!
sclp
.
has_64bscao
)
alloc_flags
|=
GFP_DMA
;
...
...
arch/s390/kvm/kvm-s390.h
View file @
650da250
...
...
@@ -242,6 +242,8 @@ static inline void kvm_s390_retry_instr(struct kvm_vcpu *vcpu)
kvm_s390_rewind_psw
(
vcpu
,
kvm_s390_get_ilen
(
vcpu
));
}
int
handle_sthyi
(
struct
kvm_vcpu
*
vcpu
);
/* implemented in priv.c */
int
is_valid_psw
(
psw_t
*
psw
);
int
kvm_s390_handle_aa
(
struct
kvm_vcpu
*
vcpu
);
...
...
@@ -268,9 +270,6 @@ void kvm_s390_vsie_destroy(struct kvm *kvm);
int
kvm_s390_handle_sigp
(
struct
kvm_vcpu
*
vcpu
);
int
kvm_s390_handle_sigp_pei
(
struct
kvm_vcpu
*
vcpu
);
/* implemented in sthyi.c */
int
handle_sthyi
(
struct
kvm_vcpu
*
vcpu
);
/* implemented in kvm-s390.c */
void
kvm_s390_set_tod_clock_ext
(
struct
kvm
*
kvm
,
const
struct
kvm_s390_vm_tod_clock
*
gtod
);
...
...
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