Re: [PATCH v8 7/8] kvmppc: Support reset of secure guest
On Tue, Sep 17, 2019 at 04:27:36PM -0700, Sukadev Bhattiprolu wrote: > > + > > + if (kvmppc_is_guest_secure(kvm)) { > > Nit: Since this entire function only applies to secure guests we could > return here for normal guests. Yes, can be done. > > bool kvmppc_is_guest_secure(struct kvm *kvm) > > { > > - return !!(kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE); > > + return (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE); > > } > > This change could be folded into PATCH 6? That was the intention but looks like I 'pick'ed wrong commit during rebase. Will fix this. > > > > unsigned long kvmppc_h_svm_init_start(struct kvm *kvm) > > @@ -85,9 +86,68 @@ unsigned long kvmppc_h_svm_init_done(struct kvm *kvm) > > return H_UNSUPPORTED; > > > > kvm->arch.secure_guest |= KVMPPC_SECURE_INIT_DONE; > > + if (kvm_is_radix(kvm)) { > > + kvmppc_free_radix(kvm); > > + pr_info("LPID %d went secure, freed HV side radix pgtables\n", > > + kvm->arch.lpid); > > + } > > return H_SUCCESS; > > } > > > > +/* > > + * Drop device pages that we maintain for the secure guest > > + * > > + * We first mark the pages to be skipped from UV_PAGE_OUT when there > > + * is HV side fault on these pages. Next we *get* these pages, forcing > > Is that get page implicit? there is no explicit "get" in this > function? gfn_to_pfn does get_user_pages eventually. > > > + * fault on them, do fault time migration to replace the device PTEs in > > + * QEMU page table with normal PTEs from newly allocated pages. > > + */ > > +static void kvmppc_uvmem_drop_pages(struct kvm_memory_slot *free, > > + struct kvm *kvm) > > +{ > > + int i; > > + struct kvmppc_uvmem_page_pvt *pvt; > > + unsigned long pfn; > > + > > + for (i = 0; i < free->npages; i++) { > > + unsigned long *rmap = >arch.rmap[i]; > > + struct page *uvmem_page; > > + > > + if (kvmppc_rmap_type(rmap) == KVMPPC_RMAP_UVMEM_PFN) { > > + uvmem_page = pfn_to_page(*rmap & > > +~KVMPPC_RMAP_UVMEM_PFN); > > + pvt = (struct kvmppc_uvmem_page_pvt *) > > + uvmem_page->zone_device_data; > > + pvt->skip_page_out = true; > > + > > + pfn = gfn_to_pfn(kvm, pvt->gpa >> PAGE_SHIFT); Regards, Bharata.
Re: [PATCH v8 7/8] kvmppc: Support reset of secure guest
Bharata B Rao [bhar...@linux.ibm.com] wrote: > 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: > > - 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. > - Reinitialize guest's partitioned scoped page tables. These are > freed when guest becomes secure (H_SVM_INIT_DONE) > - Release all device pages of the secure guest. > > After these steps, guest is ready to issue UV_ESM call once again > to switch to secure mode. > > Signed-off-by: Bharata B Rao > Signed-off-by: Sukadev Bhattiprolu > [Implementation of uv_svm_terminate() and its call from > guest shutdown path] > Signed-off-by: Ram Pai > [Unpinning of VPA pages] > --- > Documentation/virt/kvm/api.txt | 19 ++ > arch/powerpc/include/asm/kvm_book3s_uvmem.h | 7 ++ > arch/powerpc/include/asm/kvm_ppc.h | 2 + > arch/powerpc/include/asm/ultravisor-api.h | 1 + > arch/powerpc/include/asm/ultravisor.h | 5 ++ > arch/powerpc/kvm/book3s_hv.c| 74 + > arch/powerpc/kvm/book3s_hv_uvmem.c | 62 - > arch/powerpc/kvm/powerpc.c | 12 > include/uapi/linux/kvm.h| 1 + > 9 files changed, 182 insertions(+), 1 deletion(-) > > diff --git a/Documentation/virt/kvm/api.txt b/Documentation/virt/kvm/api.txt > index 2d067767b617..8e7a02e547e9 100644 > --- a/Documentation/virt/kvm/api.txt > +++ b/Documentation/virt/kvm/api.txt > @@ -4111,6 +4111,25 @@ Valid values for 'action': > #define KVM_PMU_EVENT_ALLOW 0 > #define KVM_PMU_EVENT_DENY 1 > > +4.121 KVM_PPC_SVM_OFF > + > +Capability: basic > +Architectures: powerpc > +Type: vm ioctl > +Parameters: none > +Returns: 0 on successful completion, > +Errors: > + EINVAL:if ultravisor failed to terminate the secure guest > + ENOMEM:if hypervisor failed to allocate new radix page tables for guest > + > +This ioctl is used to turn off the secure mode of the guest or transition > +the guest from secure mode to normal mode. This is invoked when the guest > +is reset. This has no effect if called for a normal guest. > + > +This ioctl issues an ultravisor call to terminate the secure guest, > +unpins the VPA pages, reinitializes guest's partition scoped page > +tables and releases all the device pages that are used to track the > +secure pages by hypervisor. > > 5. The kvm_run structure > > diff --git a/arch/powerpc/include/asm/kvm_book3s_uvmem.h > b/arch/powerpc/include/asm/kvm_book3s_uvmem.h > index fc924ef00b91..6b8cc8edd0ab 100644 > --- a/arch/powerpc/include/asm/kvm_book3s_uvmem.h > +++ b/arch/powerpc/include/asm/kvm_book3s_uvmem.h > @@ -13,6 +13,8 @@ unsigned long kvmppc_h_svm_page_out(struct kvm *kvm, > unsigned long page_shift); > unsigned long kvmppc_h_svm_init_start(struct kvm *kvm); > unsigned long kvmppc_h_svm_init_done(struct kvm *kvm); > +void kvmppc_uvmem_free_memslot_pfns(struct kvm *kvm, > + struct kvm_memslots *slots); > #else > static inline unsigned long > kvmppc_h_svm_page_in(struct kvm *kvm, unsigned long gra, > @@ -37,5 +39,10 @@ static inline unsigned long kvmppc_h_svm_init_done(struct > kvm *kvm) > { > return H_UNSUPPORTED; > } > + > +static inline void kvmppc_uvmem_free_memslot_pfns(struct kvm *kvm, > + struct kvm_memslots *slots) > +{ > +} > #endif /* CONFIG_PPC_UV */ > #endif /* __POWERPC_KVM_PPC_HMM_H__ */ > diff --git a/arch/powerpc/include/asm/kvm_ppc.h > b/arch/powerpc/include/asm/kvm_ppc.h > index 2484e6a8f5ca..e4093d067354 100644 > --- a/arch/powerpc/include/asm/kvm_ppc.h > +++ b/arch/powerpc/include/asm/kvm_ppc.h > @@ -177,6 +177,7 @@ extern void kvm_spapr_tce_release_iommu_group(struct kvm > *kvm, > extern int kvmppc_switch_mmu_to_hpt(struct kvm *kvm); > extern int kvmppc_switch_mmu_to_radix(struct kvm *kvm); > extern void kvmppc_setup_partition_table(struct kvm *kvm); > +extern int kvmppc_reinit_partition_table(struct kvm *kvm); > > extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, > struct kvm_create_spapr_tce_64 *args); > @@ -321,6 +322,7 @@ struct kvmppc_ops { > int size); > int (*store_to_eaddr)(struct kvm_vcpu *vcpu, ulong *eaddr, void *ptr, > int size); > + int (*svm_off)(struct kvm *kvm); > }; > > extern struct kvmppc_ops *kvmppc_hv_ops; > diff --git a/arch/powerpc/include/asm/ultravisor-api.h > b/arch/powerpc/include/asm/ultravisor-api.h > index cf200d4ce703..3a27a0c0be05 100644 > --- a/arch/powerpc/include/asm/ultravisor-api.h > +++
[PATCH v8 7/8] kvmppc: 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: - 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. - Reinitialize guest's partitioned scoped page tables. These are freed when guest becomes secure (H_SVM_INIT_DONE) - Release all device pages of the secure guest. After these steps, guest is ready to issue UV_ESM call once again to switch to secure mode. Signed-off-by: Bharata B Rao Signed-off-by: Sukadev Bhattiprolu [Implementation of uv_svm_terminate() and its call from guest shutdown path] Signed-off-by: Ram Pai [Unpinning of VPA pages] --- Documentation/virt/kvm/api.txt | 19 ++ arch/powerpc/include/asm/kvm_book3s_uvmem.h | 7 ++ arch/powerpc/include/asm/kvm_ppc.h | 2 + arch/powerpc/include/asm/ultravisor-api.h | 1 + arch/powerpc/include/asm/ultravisor.h | 5 ++ arch/powerpc/kvm/book3s_hv.c| 74 + arch/powerpc/kvm/book3s_hv_uvmem.c | 62 - arch/powerpc/kvm/powerpc.c | 12 include/uapi/linux/kvm.h| 1 + 9 files changed, 182 insertions(+), 1 deletion(-) diff --git a/Documentation/virt/kvm/api.txt b/Documentation/virt/kvm/api.txt index 2d067767b617..8e7a02e547e9 100644 --- a/Documentation/virt/kvm/api.txt +++ b/Documentation/virt/kvm/api.txt @@ -4111,6 +4111,25 @@ Valid values for 'action': #define KVM_PMU_EVENT_ALLOW 0 #define KVM_PMU_EVENT_DENY 1 +4.121 KVM_PPC_SVM_OFF + +Capability: basic +Architectures: powerpc +Type: vm ioctl +Parameters: none +Returns: 0 on successful completion, +Errors: + EINVAL:if ultravisor failed to terminate the secure guest + ENOMEM:if hypervisor failed to allocate new radix page tables for guest + +This ioctl is used to turn off the secure mode of the guest or transition +the guest from secure mode to normal mode. This is invoked when the guest +is reset. This has no effect if called for a normal guest. + +This ioctl issues an ultravisor call to terminate the secure guest, +unpins the VPA pages, reinitializes guest's partition scoped page +tables and releases all the device pages that are used to track the +secure pages by hypervisor. 5. The kvm_run structure diff --git a/arch/powerpc/include/asm/kvm_book3s_uvmem.h b/arch/powerpc/include/asm/kvm_book3s_uvmem.h index fc924ef00b91..6b8cc8edd0ab 100644 --- a/arch/powerpc/include/asm/kvm_book3s_uvmem.h +++ b/arch/powerpc/include/asm/kvm_book3s_uvmem.h @@ -13,6 +13,8 @@ unsigned long kvmppc_h_svm_page_out(struct kvm *kvm, unsigned long page_shift); unsigned long kvmppc_h_svm_init_start(struct kvm *kvm); unsigned long kvmppc_h_svm_init_done(struct kvm *kvm); +void kvmppc_uvmem_free_memslot_pfns(struct kvm *kvm, + struct kvm_memslots *slots); #else static inline unsigned long kvmppc_h_svm_page_in(struct kvm *kvm, unsigned long gra, @@ -37,5 +39,10 @@ static inline unsigned long kvmppc_h_svm_init_done(struct kvm *kvm) { return H_UNSUPPORTED; } + +static inline void kvmppc_uvmem_free_memslot_pfns(struct kvm *kvm, + struct kvm_memslots *slots) +{ +} #endif /* CONFIG_PPC_UV */ #endif /* __POWERPC_KVM_PPC_HMM_H__ */ diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 2484e6a8f5ca..e4093d067354 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -177,6 +177,7 @@ extern void kvm_spapr_tce_release_iommu_group(struct kvm *kvm, extern int kvmppc_switch_mmu_to_hpt(struct kvm *kvm); extern int kvmppc_switch_mmu_to_radix(struct kvm *kvm); extern void kvmppc_setup_partition_table(struct kvm *kvm); +extern int kvmppc_reinit_partition_table(struct kvm *kvm); extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, struct kvm_create_spapr_tce_64 *args); @@ -321,6 +322,7 @@ struct kvmppc_ops { int size); int (*store_to_eaddr)(struct kvm_vcpu *vcpu, ulong *eaddr, void *ptr, int size); + int (*svm_off)(struct kvm *kvm); }; extern struct kvmppc_ops *kvmppc_hv_ops; diff --git a/arch/powerpc/include/asm/ultravisor-api.h b/arch/powerpc/include/asm/ultravisor-api.h index cf200d4ce703..3a27a0c0be05 100644 --- a/arch/powerpc/include/asm/ultravisor-api.h +++ b/arch/powerpc/include/asm/ultravisor-api.h @@ -30,5 +30,6 @@ #define UV_PAGE_IN 0xF128 #define UV_PAGE_OUT0xF12C #define UV_PAGE_INVAL 0xF138 +#define UV_SVM_TERMINATE 0xF13C #endif /*