Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
650da250
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看板
提交
650da250
编写于
10月 09, 2017
作者:
C
Christian Borntraeger
浏览文件
操作
浏览文件
下载
差异文件
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
上级
2bd6bf03
3d8757b8
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
182 addition
and
71 deletion
+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
未找到文件。
arch/s390/include/asm/kvm_host.h
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录