Skip to content

Commit 2294568

Browse files
Bharata B Raopaulusmack
authored andcommitted
KVM: PPC: Book3S HV: Support reset of secure guest
Add support for reset of secure guest via a new ioctl KVM_PPC_SVM_OFF. This ioctl will be issued by QEMU during reset and includes the the following steps: - Release all device pages of the secure guest. - Ask UV to terminate the guest via UV_SVM_TERMINATE ucall - Unpin the VPA pages so that they can be migrated back to secure side when guest becomes secure again. This is required because pinned pages can't be migrated. - Reinit the partition scoped page tables After these steps, guest is ready to issue UV_ESM call once again to switch to secure mode. Signed-off-by: Bharata B Rao <[email protected]> Signed-off-by: Sukadev Bhattiprolu <[email protected]> [Implementation of uv_svm_terminate() and its call from guest shutdown path] Signed-off-by: Ram Pai <[email protected]> [Unpinning of VPA pages] Signed-off-by: Paul Mackerras <[email protected]>
1 parent c326225 commit 2294568

File tree

7 files changed

+128
-0
lines changed

7 files changed

+128
-0
lines changed

Documentation/virt/kvm/api.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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/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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
#define UV_UNSHARE_PAGE 0xF134
3535
#define UV_UNSHARE_ALL_PAGES 0xF140
3636
#define UV_PAGE_INVAL 0xF138
37+
#define UV_SVM_TERMINATE 0xF13C
3738

3839
#endif /* _ASM_POWERPC_ULTRAVISOR_API_H */

arch/powerpc/include/asm/ultravisor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,9 @@ static inline int uv_page_inval(u64 lpid, u64 gpa, u64 page_shift)
7777
return ucall_norets(UV_PAGE_INVAL, lpid, gpa, page_shift);
7878
}
7979

80+
static inline int uv_svm_terminate(u64 lpid)
81+
{
82+
return ucall_norets(UV_SVM_TERMINATE, lpid);
83+
}
84+
8085
#endif /* _ASM_POWERPC_ULTRAVISOR_H */

arch/powerpc/kvm/book3s_hv.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4983,6 +4983,7 @@ static void kvmppc_core_destroy_vm_hv(struct kvm *kvm)
49834983
if (nesting_enabled(kvm))
49844984
kvmhv_release_all_nested(kvm);
49854985
kvm->arch.process_table = 0;
4986+
uv_svm_terminate(kvm->arch.lpid);
49864987
kvmhv_set_ptbl_entry(kvm->arch.lpid, 0, 0);
49874988
}
49884989

@@ -5425,6 +5426,94 @@ static int kvmhv_store_to_eaddr(struct kvm_vcpu *vcpu, ulong *eaddr, void *ptr,
54255426
return rc;
54265427
}
54275428

5429+
static void unpin_vpa_reset(struct kvm *kvm, struct kvmppc_vpa *vpa)
5430+
{
5431+
unpin_vpa(kvm, vpa);
5432+
vpa->gpa = 0;
5433+
vpa->pinned_addr = NULL;
5434+
vpa->dirty = false;
5435+
vpa->update_pending = 0;
5436+
}
5437+
5438+
/*
5439+
* IOCTL handler to turn off secure mode of guest
5440+
*
5441+
* - Release all device pages
5442+
* - Issue ucall to terminate the guest on the UV side
5443+
* - Unpin the VPA pages.
5444+
* - Reinit the partition scoped page tables
5445+
*/
5446+
static int kvmhv_svm_off(struct kvm *kvm)
5447+
{
5448+
struct kvm_vcpu *vcpu;
5449+
int mmu_was_ready;
5450+
int srcu_idx;
5451+
int ret = 0;
5452+
int i;
5453+
5454+
if (!(kvm->arch.secure_guest & KVMPPC_SECURE_INIT_START))
5455+
return ret;
5456+
5457+
mutex_lock(&kvm->arch.mmu_setup_lock);
5458+
mmu_was_ready = kvm->arch.mmu_ready;
5459+
if (kvm->arch.mmu_ready) {
5460+
kvm->arch.mmu_ready = 0;
5461+
/* order mmu_ready vs. vcpus_running */
5462+
smp_mb();
5463+
if (atomic_read(&kvm->arch.vcpus_running)) {
5464+
kvm->arch.mmu_ready = 1;
5465+
ret = -EBUSY;
5466+
goto out;
5467+
}
5468+
}
5469+
5470+
srcu_idx = srcu_read_lock(&kvm->srcu);
5471+
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
5472+
struct kvm_memory_slot *memslot;
5473+
struct kvm_memslots *slots = __kvm_memslots(kvm, i);
5474+
5475+
if (!slots)
5476+
continue;
5477+
5478+
kvm_for_each_memslot(memslot, slots) {
5479+
kvmppc_uvmem_drop_pages(memslot, kvm);
5480+
uv_unregister_mem_slot(kvm->arch.lpid, memslot->id);
5481+
}
5482+
}
5483+
srcu_read_unlock(&kvm->srcu, srcu_idx);
5484+
5485+
ret = uv_svm_terminate(kvm->arch.lpid);
5486+
if (ret != U_SUCCESS) {
5487+
ret = -EINVAL;
5488+
goto out;
5489+
}
5490+
5491+
/*
5492+
* When secure guest is reset, all the guest pages are sent
5493+
* to UV via UV_PAGE_IN before the non-boot vcpus get a
5494+
* chance to run and unpin their VPA pages. Unpinning of all
5495+
* VPA pages is done here explicitly so that VPA pages
5496+
* can be migrated to the secure side.
5497+
*
5498+
* This is required to for the secure SMP guest to reboot
5499+
* correctly.
5500+
*/
5501+
kvm_for_each_vcpu(i, vcpu, kvm) {
5502+
spin_lock(&vcpu->arch.vpa_update_lock);
5503+
unpin_vpa_reset(kvm, &vcpu->arch.dtl);
5504+
unpin_vpa_reset(kvm, &vcpu->arch.slb_shadow);
5505+
unpin_vpa_reset(kvm, &vcpu->arch.vpa);
5506+
spin_unlock(&vcpu->arch.vpa_update_lock);
5507+
}
5508+
5509+
kvmppc_setup_partition_table(kvm);
5510+
kvm->arch.secure_guest = 0;
5511+
kvm->arch.mmu_ready = mmu_was_ready;
5512+
out:
5513+
mutex_unlock(&kvm->arch.mmu_setup_lock);
5514+
return ret;
5515+
}
5516+
54285517
static struct kvmppc_ops kvm_ops_hv = {
54295518
.get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv,
54305519
.set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv,
@@ -5468,6 +5557,7 @@ static struct kvmppc_ops kvm_ops_hv = {
54685557
.enable_nested = kvmhv_enable_nested,
54695558
.load_from_eaddr = kvmhv_load_from_eaddr,
54705559
.store_to_eaddr = kvmhv_store_to_eaddr,
5560+
.svm_off = kvmhv_svm_off,
54715561
};
54725562

54735563
static int kvm_init_subcore_bitmap(void)

arch/powerpc/kvm/powerpc.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include <asm/hvcall.h>
3232
#include <asm/plpar_wrappers.h>
3333
#endif
34+
#include <asm/ultravisor.h>
35+
#include <asm/kvm_host.h>
3436

3537
#include "timing.h"
3638
#include "irq.h"
@@ -2413,6 +2415,16 @@ long kvm_arch_vm_ioctl(struct file *filp,
24132415
r = -EFAULT;
24142416
break;
24152417
}
2418+
case KVM_PPC_SVM_OFF: {
2419+
struct kvm *kvm = filp->private_data;
2420+
2421+
r = 0;
2422+
if (!kvm->arch.kvm_ops->svm_off)
2423+
goto out;
2424+
2425+
r = kvm->arch.kvm_ops->svm_off(kvm);
2426+
break;
2427+
}
24162428
default: {
24172429
struct kvm *kvm = filp->private_data;
24182430
r = kvm->arch.kvm_ops->arch_vm_ioctl(filp, ioctl, arg);

include/uapi/linux/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,7 @@ struct kvm_s390_ucas_mapping {
13481348
#define KVM_PPC_GET_CPU_CHAR _IOR(KVMIO, 0xb1, struct kvm_ppc_cpu_char)
13491349
/* Available with KVM_CAP_PMU_EVENT_FILTER */
13501350
#define KVM_SET_PMU_EVENT_FILTER _IOW(KVMIO, 0xb2, struct kvm_pmu_event_filter)
1351+
#define KVM_PPC_SVM_OFF _IO(KVMIO, 0xb3)
13511352

13521353
/* ioctl for vm fd */
13531354
#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)

0 commit comments

Comments
 (0)