Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
cb547637
cloud-kernel
项目概览
openanolis
/
cloud-kernel
大约 1 年 前同步成功
通知
158
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看板
体验新版 GitCode,发现更多精彩内容 >>
提交
cb547637
编写于
7月 28, 2018
作者:
P
Paolo Bonzini
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
kvm: selftests: add test for nested state save/restore
Signed-off-by:
N
Paolo Bonzini
<
pbonzini@redhat.com
>
上级
8fcc4b59
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
132 addition
and
1 deletion
+132
-1
tools/testing/selftests/kvm/include/vmx.h
tools/testing/selftests/kvm/include/vmx.h
+33
-0
tools/testing/selftests/kvm/lib/x86.c
tools/testing/selftests/kvm/lib/x86.c
+29
-0
tools/testing/selftests/kvm/state_test.c
tools/testing/selftests/kvm/state_test.c
+70
-1
未找到文件。
tools/testing/selftests/kvm/include/vmx.h
浏览文件 @
cb547637
...
...
@@ -380,6 +380,30 @@ static inline int vmptrld(uint64_t vmcs_pa)
return
ret
;
}
static
inline
int
vmptrst
(
uint64_t
*
value
)
{
uint64_t
tmp
;
uint8_t
ret
;
__asm__
__volatile__
(
"vmptrst %[value]; setna %[ret]"
:
[
value
]
"=m"
(
tmp
),
[
ret
]
"=rm"
(
ret
)
:
:
"cc"
,
"memory"
);
*
value
=
tmp
;
return
ret
;
}
/*
* A wrapper around vmptrst that ignores errors and returns zero if the
* vmptrst instruction fails.
*/
static
inline
uint64_t
vmptrstz
(
void
)
{
uint64_t
value
=
0
;
vmptrst
(
&
value
);
return
value
;
}
/*
* No guest state (e.g. GPRs) is established by this vmlaunch.
*/
...
...
@@ -444,6 +468,15 @@ static inline int vmresume(void)
return
ret
;
}
static
inline
void
vmcall
(
void
)
{
/* Currently, L1 destroys our GPRs during vmexits. */
__asm__
__volatile__
(
"push %%rbp; vmcall; pop %%rbp"
:
:
:
"rax"
,
"rbx"
,
"rcx"
,
"rdx"
,
"rsi"
,
"rdi"
,
"r8"
,
"r9"
,
"r10"
,
"r11"
,
"r12"
,
"r13"
,
"r14"
,
"r15"
);
}
static
inline
int
vmread
(
uint64_t
encoding
,
uint64_t
*
value
)
{
uint64_t
tmp
;
...
...
tools/testing/selftests/kvm/lib/x86.c
浏览文件 @
cb547637
...
...
@@ -736,6 +736,10 @@ struct kvm_x86_state {
struct
kvm_xcrs
xcrs
;
struct
kvm_sregs
sregs
;
struct
kvm_debugregs
debugregs
;
union
{
struct
kvm_nested_state
nested
;
char
nested_
[
16384
];
};
struct
kvm_msrs
msrs
;
};
...
...
@@ -758,6 +762,14 @@ struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
struct
kvm_msr_list
*
list
;
struct
kvm_x86_state
*
state
;
int
nmsrs
,
r
,
i
;
static
int
nested_size
=
-
1
;
if
(
nested_size
==
-
1
)
{
nested_size
=
kvm_check_cap
(
KVM_CAP_NESTED_STATE
);
TEST_ASSERT
(
nested_size
<=
sizeof
(
state
->
nested_
),
"Nested state size too big, %i > %zi"
,
nested_size
,
sizeof
(
state
->
nested_
));
}
nmsrs
=
kvm_get_num_msrs
(
vm
);
list
=
malloc
(
sizeof
(
*
list
)
+
nmsrs
*
sizeof
(
list
->
indices
[
0
]));
...
...
@@ -791,6 +803,17 @@ struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
TEST_ASSERT
(
r
==
0
,
"Unexpected result from KVM_GET_SREGS, r: %i"
,
r
);
if
(
nested_size
)
{
state
->
nested
.
size
=
sizeof
(
state
->
nested_
);
r
=
ioctl
(
vcpu
->
fd
,
KVM_GET_NESTED_STATE
,
&
state
->
nested
);
TEST_ASSERT
(
r
==
0
,
"Unexpected result from KVM_GET_NESTED_STATE, r: %i"
,
r
);
TEST_ASSERT
(
state
->
nested
.
size
<=
nested_size
,
"Nested state size too big, %i (KVM_CHECK_CAP gave %i)"
,
state
->
nested
.
size
,
nested_size
);
}
else
state
->
nested
.
size
=
0
;
state
->
msrs
.
nmsrs
=
nmsrs
;
for
(
i
=
0
;
i
<
nmsrs
;
i
++
)
state
->
msrs
.
entries
[
i
].
index
=
list
->
indices
[
i
];
...
...
@@ -811,6 +834,12 @@ void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *s
struct
vcpu
*
vcpu
=
vcpu_find
(
vm
,
vcpuid
);
int
r
;
if
(
state
->
nested
.
size
)
{
r
=
ioctl
(
vcpu
->
fd
,
KVM_SET_NESTED_STATE
,
&
state
->
nested
);
TEST_ASSERT
(
r
==
0
,
"Unexpected result from KVM_SET_NESTED_STATE, r: %i"
,
r
);
}
r
=
ioctl
(
vcpu
->
fd
,
KVM_SET_XSAVE
,
&
state
->
xsave
);
TEST_ASSERT
(
r
==
0
,
"Unexpected result from KVM_SET_XSAVE, r: %i"
,
r
);
...
...
tools/testing/selftests/kvm/state_test.c
浏览文件 @
cb547637
...
...
@@ -18,6 +18,7 @@
#include "kvm_util.h"
#include "x86.h"
#include "vmx.h"
#define VCPU_ID 5
#define PORT_SYNC 0x1000
...
...
@@ -45,16 +46,75 @@ static inline void __exit_to_l0(uint16_t port, uint64_t arg0, uint64_t arg1)
static
bool
have_nested_state
;
void
guest_code
(
void
)
void
l2_guest_code
(
void
)
{
GUEST_SYNC
(
5
);
/* Exit to L1 */
vmcall
();
GUEST_SYNC
(
7
);
/* Done, exit to L1 and never come back. */
vmcall
();
}
void
l1_guest_code
(
struct
vmx_pages
*
vmx_pages
)
{
#define L2_GUEST_STACK_SIZE 64
unsigned
long
l2_guest_stack
[
L2_GUEST_STACK_SIZE
];
GUEST_ASSERT
(
vmx_pages
->
vmcs_gpa
);
GUEST_ASSERT
(
prepare_for_vmx_operation
(
vmx_pages
));
GUEST_ASSERT
(
vmptrstz
()
==
vmx_pages
->
vmcs_gpa
);
GUEST_SYNC
(
3
);
GUEST_ASSERT
(
vmptrstz
()
==
vmx_pages
->
vmcs_gpa
);
prepare_vmcs
(
vmx_pages
,
l2_guest_code
,
&
l2_guest_stack
[
L2_GUEST_STACK_SIZE
]);
GUEST_SYNC
(
4
);
GUEST_ASSERT
(
vmptrstz
()
==
vmx_pages
->
vmcs_gpa
);
GUEST_ASSERT
(
!
vmlaunch
());
GUEST_ASSERT
(
vmptrstz
()
==
vmx_pages
->
vmcs_gpa
);
GUEST_ASSERT
(
vmreadz
(
VM_EXIT_REASON
)
==
EXIT_REASON_VMCALL
);
/* Check that the launched state is preserved. */
GUEST_ASSERT
(
vmlaunch
());
GUEST_ASSERT
(
!
vmresume
());
GUEST_ASSERT
(
vmreadz
(
VM_EXIT_REASON
)
==
EXIT_REASON_VMCALL
);
GUEST_SYNC
(
6
);
GUEST_ASSERT
(
vmreadz
(
VM_EXIT_REASON
)
==
EXIT_REASON_VMCALL
);
GUEST_ASSERT
(
!
vmresume
());
GUEST_ASSERT
(
vmreadz
(
VM_EXIT_REASON
)
==
EXIT_REASON_VMCALL
);
vmwrite
(
GUEST_RIP
,
vmreadz
(
GUEST_RIP
)
+
3
);
GUEST_ASSERT
(
!
vmresume
());
GUEST_ASSERT
(
vmreadz
(
VM_EXIT_REASON
)
==
EXIT_REASON_VMCALL
);
GUEST_SYNC
(
8
);
}
void
guest_code
(
struct
vmx_pages
*
vmx_pages
)
{
GUEST_SYNC
(
1
);
GUEST_SYNC
(
2
);
if
(
vmx_pages
)
l1_guest_code
(
vmx_pages
);
exit_to_l0
(
PORT_DONE
,
0
,
0
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
struct
vmx_pages
*
vmx_pages
=
NULL
;
vm_vaddr_t
vmx_pages_gva
=
0
;
struct
kvm_regs
regs1
,
regs2
;
struct
kvm_vm
*
vm
;
struct
kvm_run
*
run
;
...
...
@@ -69,6 +129,15 @@ int main(int argc, char *argv[])
run
=
vcpu_state
(
vm
,
VCPU_ID
);
vcpu_regs_get
(
vm
,
VCPU_ID
,
&
regs1
);
if
(
kvm_check_cap
(
KVM_CAP_NESTED_STATE
))
{
vmx_pages
=
vcpu_alloc_vmx
(
vm
,
&
vmx_pages_gva
);
vcpu_args_set
(
vm
,
VCPU_ID
,
1
,
vmx_pages_gva
);
}
else
{
printf
(
"will skip nested state checks
\n
"
);
vcpu_args_set
(
vm
,
VCPU_ID
,
1
,
0
);
}
for
(
stage
=
1
;;
stage
++
)
{
_vcpu_run
(
vm
,
VCPU_ID
);
TEST_ASSERT
(
run
->
exit_reason
==
KVM_EXIT_IO
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录