Skip to content

Commit aedc065

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull more KVM updates from Paolo Bonzini: - PPC secure guest support - small x86 cleanup - fix for an x86-specific out-of-bounds write on a ioctl (not guest triggerable, data not attacker-controlled) * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: kvm: vmx: Stop wasting a page for guest_msrs KVM: x86: fix out-of-bounds write in KVM_GET_EMULATED_CPUID (CVE-2019-19332) Documentation: kvm: Fix mention to number of ioctls classes powerpc: Ultravisor: Add PPC_UV config option KVM: PPC: Book3S HV: Support reset of secure guest KVM: PPC: Book3S HV: Handle memory plug/unplug to secure VM KVM: PPC: Book3S HV: Radix changes for secure guest KVM: PPC: Book3S HV: Shared pages support for secure guests KVM: PPC: Book3S HV: Support for running secure guests mm: ksm: Export ksm_madvise() KVM x86: Move kvm cpuid support out of svm
2 parents 6cdc7f2 + 7d73710 commit aedc065

File tree

19 files changed

+1156
-20
lines changed

19 files changed

+1156
-20
lines changed

Documentation/virt/kvm/api.txt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ The Definitive KVM (Kernel-based Virtual Machine) API Documentation
55
----------------------
66

77
The kvm API is a set of ioctls that are issued to control various aspects
8-
of a virtual machine. The ioctls belong to three classes:
8+
of a virtual machine. The ioctls belong to the following classes:
99

1010
- System ioctls: These query and set global attributes which affect the
1111
whole kvm subsystem. In addition a system ioctl is used to create
@@ -4149,6 +4149,24 @@ Valid values for 'action':
41494149
#define KVM_PMU_EVENT_ALLOW 0
41504150
#define KVM_PMU_EVENT_DENY 1
41514151

4152+
4.121 KVM_PPC_SVM_OFF
4153+
4154+
Capability: basic
4155+
Architectures: powerpc
4156+
Type: vm ioctl
4157+
Parameters: none
4158+
Returns: 0 on successful completion,
4159+
Errors:
4160+
EINVAL: if ultravisor failed to terminate the secure guest
4161+
ENOMEM: if hypervisor failed to allocate new radix page tables for guest
4162+
4163+
This ioctl is used to turn off the secure mode of the guest or transition
4164+
the guest from secure mode to normal mode. This is invoked when the guest
4165+
is reset. This has no effect if called for a normal guest.
4166+
4167+
This ioctl issues an ultravisor call to terminate the secure guest,
4168+
unpins the VPA pages and releases all the device pages that are used to
4169+
track the secure pages by hypervisor.
41524170

41534171
5. The kvm_run structure
41544172
------------------------

arch/powerpc/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,23 @@ config PPC_TRANSACTIONAL_MEM
452452
help
453453
Support user-mode Transactional Memory on POWERPC.
454454

455+
config PPC_UV
456+
bool "Ultravisor support"
457+
depends on KVM_BOOK3S_HV_POSSIBLE
458+
select ZONE_DEVICE
459+
select DEV_PAGEMAP_OPS
460+
select DEVICE_PRIVATE
461+
select MEMORY_HOTPLUG
462+
select MEMORY_HOTREMOVE
463+
default n
464+
help
465+
This option paravirtualizes the kernel to run in POWER platforms that
466+
supports the Protected Execution Facility (PEF). On such platforms,
467+
the ultravisor firmware runs at a privilege level above the
468+
hypervisor.
469+
470+
If unsure, say "N".
471+
455472
config LD_HEAD_STUB_CATCH
456473
bool "Reserve 256 bytes to cope with linker stubs in HEAD text" if EXPERT
457474
depends on PPC64

arch/powerpc/include/asm/hvcall.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,15 @@
342342
#define H_TLB_INVALIDATE 0xF808
343343
#define H_COPY_TOFROM_GUEST 0xF80C
344344

345+
/* Flags for H_SVM_PAGE_IN */
346+
#define H_PAGE_IN_SHARED 0x1
347+
348+
/* Platform-specific hcalls used by the Ultravisor */
349+
#define H_SVM_PAGE_IN 0xEF00
350+
#define H_SVM_PAGE_OUT 0xEF04
351+
#define H_SVM_INIT_START 0xEF08
352+
#define H_SVM_INIT_DONE 0xEF0C
353+
345354
/* Values for 2nd argument to H_SET_MODE */
346355
#define H_SET_MODE_RESOURCE_SET_CIABR 1
347356
#define H_SET_MODE_RESOURCE_SET_DAWR 2
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __ASM_KVM_BOOK3S_UVMEM_H__
3+
#define __ASM_KVM_BOOK3S_UVMEM_H__
4+
5+
#ifdef CONFIG_PPC_UV
6+
int kvmppc_uvmem_init(void);
7+
void kvmppc_uvmem_free(void);
8+
int kvmppc_uvmem_slot_init(struct kvm *kvm, const struct kvm_memory_slot *slot);
9+
void kvmppc_uvmem_slot_free(struct kvm *kvm,
10+
const struct kvm_memory_slot *slot);
11+
unsigned long kvmppc_h_svm_page_in(struct kvm *kvm,
12+
unsigned long gra,
13+
unsigned long flags,
14+
unsigned long page_shift);
15+
unsigned long kvmppc_h_svm_page_out(struct kvm *kvm,
16+
unsigned long gra,
17+
unsigned long flags,
18+
unsigned long page_shift);
19+
unsigned long kvmppc_h_svm_init_start(struct kvm *kvm);
20+
unsigned long kvmppc_h_svm_init_done(struct kvm *kvm);
21+
int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn);
22+
void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
23+
struct kvm *kvm);
24+
#else
25+
static inline int kvmppc_uvmem_init(void)
26+
{
27+
return 0;
28+
}
29+
30+
static inline void kvmppc_uvmem_free(void) { }
31+
32+
static inline int
33+
kvmppc_uvmem_slot_init(struct kvm *kvm, const struct kvm_memory_slot *slot)
34+
{
35+
return 0;
36+
}
37+
38+
static inline void
39+
kvmppc_uvmem_slot_free(struct kvm *kvm, const struct kvm_memory_slot *slot) { }
40+
41+
static inline unsigned long
42+
kvmppc_h_svm_page_in(struct kvm *kvm, unsigned long gra,
43+
unsigned long flags, unsigned long page_shift)
44+
{
45+
return H_UNSUPPORTED;
46+
}
47+
48+
static inline unsigned long
49+
kvmppc_h_svm_page_out(struct kvm *kvm, unsigned long gra,
50+
unsigned long flags, unsigned long page_shift)
51+
{
52+
return H_UNSUPPORTED;
53+
}
54+
55+
static inline unsigned long kvmppc_h_svm_init_start(struct kvm *kvm)
56+
{
57+
return H_UNSUPPORTED;
58+
}
59+
60+
static inline unsigned long kvmppc_h_svm_init_done(struct kvm *kvm)
61+
{
62+
return H_UNSUPPORTED;
63+
}
64+
65+
static inline int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn)
66+
{
67+
return -EFAULT;
68+
}
69+
70+
static inline void
71+
kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
72+
struct kvm *kvm) { }
73+
#endif /* CONFIG_PPC_UV */
74+
#endif /* __ASM_KVM_BOOK3S_UVMEM_H__ */

arch/powerpc/include/asm/kvm_host.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,10 @@ struct kvm_hpt_info {
275275

276276
struct kvm_resize_hpt;
277277

278+
/* Flag values for kvm_arch.secure_guest */
279+
#define KVMPPC_SECURE_INIT_START 0x1 /* H_SVM_INIT_START has been called */
280+
#define KVMPPC_SECURE_INIT_DONE 0x2 /* H_SVM_INIT_DONE completed */
281+
278282
struct kvm_arch {
279283
unsigned int lpid;
280284
unsigned int smt_mode; /* # vcpus per virtual core */
@@ -330,6 +334,8 @@ struct kvm_arch {
330334
#endif
331335
struct kvmppc_ops *kvm_ops;
332336
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
337+
struct mutex uvmem_lock;
338+
struct list_head uvmem_pfns;
333339
struct mutex mmu_setup_lock; /* nests inside vcpu mutexes */
334340
u64 l1_ptcr;
335341
int max_nested_lpid;

arch/powerpc/include/asm/kvm_ppc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ struct kvmppc_ops {
322322
int size);
323323
int (*store_to_eaddr)(struct kvm_vcpu *vcpu, ulong *eaddr, void *ptr,
324324
int size);
325+
int (*svm_off)(struct kvm *kvm);
325326
};
326327

327328
extern struct kvmppc_ops *kvmppc_hv_ops;

arch/powerpc/include/asm/ultravisor-api.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,14 @@
2626
#define UV_WRITE_PATE 0xF104
2727
#define UV_RETURN 0xF11C
2828
#define UV_ESM 0xF110
29+
#define UV_REGISTER_MEM_SLOT 0xF120
30+
#define UV_UNREGISTER_MEM_SLOT 0xF124
31+
#define UV_PAGE_IN 0xF128
32+
#define UV_PAGE_OUT 0xF12C
2933
#define UV_SHARE_PAGE 0xF130
3034
#define UV_UNSHARE_PAGE 0xF134
3135
#define UV_UNSHARE_ALL_PAGES 0xF140
36+
#define UV_PAGE_INVAL 0xF138
37+
#define UV_SVM_TERMINATE 0xF13C
3238

3339
#endif /* _ASM_POWERPC_ULTRAVISOR_API_H */

arch/powerpc/include/asm/ultravisor.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,40 @@ static inline int uv_unshare_all_pages(void)
4646
return ucall_norets(UV_UNSHARE_ALL_PAGES);
4747
}
4848

49+
static inline int uv_page_in(u64 lpid, u64 src_ra, u64 dst_gpa, u64 flags,
50+
u64 page_shift)
51+
{
52+
return ucall_norets(UV_PAGE_IN, lpid, src_ra, dst_gpa, flags,
53+
page_shift);
54+
}
55+
56+
static inline int uv_page_out(u64 lpid, u64 dst_ra, u64 src_gpa, u64 flags,
57+
u64 page_shift)
58+
{
59+
return ucall_norets(UV_PAGE_OUT, lpid, dst_ra, src_gpa, flags,
60+
page_shift);
61+
}
62+
63+
static inline int uv_register_mem_slot(u64 lpid, u64 start_gpa, u64 size,
64+
u64 flags, u64 slotid)
65+
{
66+
return ucall_norets(UV_REGISTER_MEM_SLOT, lpid, start_gpa,
67+
size, flags, slotid);
68+
}
69+
70+
static inline int uv_unregister_mem_slot(u64 lpid, u64 slotid)
71+
{
72+
return ucall_norets(UV_UNREGISTER_MEM_SLOT, lpid, slotid);
73+
}
74+
75+
static inline int uv_page_inval(u64 lpid, u64 gpa, u64 page_shift)
76+
{
77+
return ucall_norets(UV_PAGE_INVAL, lpid, gpa, page_shift);
78+
}
79+
80+
static inline int uv_svm_terminate(u64 lpid)
81+
{
82+
return ucall_norets(UV_SVM_TERMINATE, lpid);
83+
}
84+
4985
#endif /* _ASM_POWERPC_ULTRAVISOR_H */

arch/powerpc/kvm/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ kvm-hv-y += \
7171
book3s_64_mmu_radix.o \
7272
book3s_hv_nested.o
7373

74+
kvm-hv-$(CONFIG_PPC_UV) += \
75+
book3s_hv_uvmem.o
76+
7477
kvm-hv-$(CONFIG_PPC_TRANSACTIONAL_MEM) += \
7578
book3s_hv_tm.o
7679

arch/powerpc/kvm/book3s_64_mmu_radix.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <asm/pgtable.h>
2020
#include <asm/pgalloc.h>
2121
#include <asm/pte-walk.h>
22+
#include <asm/ultravisor.h>
23+
#include <asm/kvm_book3s_uvmem.h>
2224

2325
/*
2426
* Supported radix tree geometry.
@@ -915,6 +917,9 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
915917
if (!(dsisr & DSISR_PRTABLE_FAULT))
916918
gpa |= ea & 0xfff;
917919

920+
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
921+
return kvmppc_send_page_to_uv(kvm, gfn);
922+
918923
/* Get the corresponding memslot */
919924
memslot = gfn_to_memslot(kvm, gfn);
920925

@@ -972,6 +977,11 @@ int kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
972977
unsigned long gpa = gfn << PAGE_SHIFT;
973978
unsigned int shift;
974979

980+
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE) {
981+
uv_page_inval(kvm->arch.lpid, gpa, PAGE_SHIFT);
982+
return 0;
983+
}
984+
975985
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
976986
if (ptep && pte_present(*ptep))
977987
kvmppc_unmap_pte(kvm, ptep, gpa, shift, memslot,
@@ -989,6 +999,9 @@ int kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
989999
int ref = 0;
9901000
unsigned long old, *rmapp;
9911001

1002+
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
1003+
return ref;
1004+
9921005
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
9931006
if (ptep && pte_present(*ptep) && pte_young(*ptep)) {
9941007
old = kvmppc_radix_update_pte(kvm, ptep, _PAGE_ACCESSED, 0,
@@ -1013,6 +1026,9 @@ int kvm_test_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
10131026
unsigned int shift;
10141027
int ref = 0;
10151028

1029+
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
1030+
return ref;
1031+
10161032
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
10171033
if (ptep && pte_present(*ptep) && pte_young(*ptep))
10181034
ref = 1;
@@ -1030,6 +1046,9 @@ static int kvm_radix_test_clear_dirty(struct kvm *kvm,
10301046
int ret = 0;
10311047
unsigned long old, *rmapp;
10321048

1049+
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
1050+
return ret;
1051+
10331052
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
10341053
if (ptep && pte_present(*ptep) && pte_dirty(*ptep)) {
10351054
ret = 1;
@@ -1082,6 +1101,12 @@ void kvmppc_radix_flush_memslot(struct kvm *kvm,
10821101
unsigned long gpa;
10831102
unsigned int shift;
10841103

1104+
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_START)
1105+
kvmppc_uvmem_drop_pages(memslot, kvm);
1106+
1107+
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
1108+
return;
1109+
10851110
gpa = memslot->base_gfn << PAGE_SHIFT;
10861111
spin_lock(&kvm->mmu_lock);
10871112
for (n = memslot->npages; n; --n) {

0 commit comments

Comments
 (0)