1ca9f4942SBharata B Rao // SPDX-License-Identifier: GPL-2.0 2ca9f4942SBharata B Rao /* 3ca9f4942SBharata B Rao * Secure pages management: Migration of pages between normal and secure 4ca9f4942SBharata B Rao * memory of KVM guests. 5ca9f4942SBharata B Rao * 6ca9f4942SBharata B Rao * Copyright 2018 Bharata B Rao, IBM Corp. <bharata@linux.ibm.com> 7ca9f4942SBharata B Rao */ 8ca9f4942SBharata B Rao 9ca9f4942SBharata B Rao /* 10ca9f4942SBharata B Rao * A pseries guest can be run as secure guest on Ultravisor-enabled 11ca9f4942SBharata B Rao * POWER platforms. On such platforms, this driver will be used to manage 12ca9f4942SBharata B Rao * the movement of guest pages between the normal memory managed by 13ca9f4942SBharata B Rao * hypervisor (HV) and secure memory managed by Ultravisor (UV). 14ca9f4942SBharata B Rao * 15ca9f4942SBharata B Rao * The page-in or page-out requests from UV will come to HV as hcalls and 16ca9f4942SBharata B Rao * HV will call back into UV via ultracalls to satisfy these page requests. 17ca9f4942SBharata B Rao * 18ca9f4942SBharata B Rao * Private ZONE_DEVICE memory equal to the amount of secure memory 19ca9f4942SBharata B Rao * available in the platform for running secure guests is hotplugged. 20ca9f4942SBharata B Rao * Whenever a page belonging to the guest becomes secure, a page from this 21ca9f4942SBharata B Rao * private device memory is used to represent and track that secure page 2260f0a643SBharata B Rao * on the HV side. Some pages (like virtio buffers, VPA pages etc) are 2360f0a643SBharata B Rao * shared between UV and HV. However such pages aren't represented by 2460f0a643SBharata B Rao * device private memory and mappings to shared memory exist in both 2560f0a643SBharata B Rao * UV and HV page tables. 26ca9f4942SBharata B Rao */ 27ca9f4942SBharata B Rao 28ca9f4942SBharata B Rao /* 29ca9f4942SBharata B Rao * Notes on locking 30ca9f4942SBharata B Rao * 31ca9f4942SBharata B Rao * kvm->arch.uvmem_lock is a per-guest lock that prevents concurrent 32ca9f4942SBharata B Rao * page-in and page-out requests for the same GPA. Concurrent accesses 33ca9f4942SBharata B Rao * can either come via UV (guest vCPUs requesting for same page) 34ca9f4942SBharata B Rao * or when HV and guest simultaneously access the same page. 35ca9f4942SBharata B Rao * This mutex serializes the migration of page from HV(normal) to 36ca9f4942SBharata B Rao * UV(secure) and vice versa. So the serialization points are around 37ca9f4942SBharata B Rao * migrate_vma routines and page-in/out routines. 38ca9f4942SBharata B Rao * 39ca9f4942SBharata B Rao * Per-guest mutex comes with a cost though. Mainly it serializes the 40ca9f4942SBharata B Rao * fault path as page-out can occur when HV faults on accessing secure 41ca9f4942SBharata B Rao * guest pages. Currently UV issues page-in requests for all the guest 42ca9f4942SBharata B Rao * PFNs one at a time during early boot (UV_ESM uvcall), so this is 43ca9f4942SBharata B Rao * not a cause for concern. Also currently the number of page-outs caused 44ca9f4942SBharata B Rao * by HV touching secure pages is very very low. If an when UV supports 45ca9f4942SBharata B Rao * overcommitting, then we might see concurrent guest driven page-outs. 46ca9f4942SBharata B Rao * 47ca9f4942SBharata B Rao * Locking order 48ca9f4942SBharata B Rao * 49ca9f4942SBharata B Rao * 1. kvm->srcu - Protects KVM memslots 50c1e8d7c6SMichel Lespinasse * 2. kvm->mm->mmap_lock - find_vma, migrate_vma_pages and helpers, ksm_madvise 51ca9f4942SBharata B Rao * 3. kvm->arch.uvmem_lock - protects read/writes to uvmem slots thus acting 52ca9f4942SBharata B Rao * as sync-points for page-in/out 53ca9f4942SBharata B Rao */ 54ca9f4942SBharata B Rao 55ca9f4942SBharata B Rao /* 56ca9f4942SBharata B Rao * Notes on page size 57ca9f4942SBharata B Rao * 58ca9f4942SBharata B Rao * Currently UV uses 2MB mappings internally, but will issue H_SVM_PAGE_IN 59ca9f4942SBharata B Rao * and H_SVM_PAGE_OUT hcalls in PAGE_SIZE(64K) granularity. HV tracks 60ca9f4942SBharata B Rao * secure GPAs at 64K page size and maintains one device PFN for each 61ca9f4942SBharata B Rao * 64K secure GPA. UV_PAGE_IN and UV_PAGE_OUT calls by HV are also issued 62ca9f4942SBharata B Rao * for 64K page at a time. 63ca9f4942SBharata B Rao * 64ca9f4942SBharata B Rao * HV faulting on secure pages: When HV touches any secure page, it 65ca9f4942SBharata B Rao * faults and issues a UV_PAGE_OUT request with 64K page size. Currently 66ca9f4942SBharata B Rao * UV splits and remaps the 2MB page if necessary and copies out the 67ca9f4942SBharata B Rao * required 64K page contents. 68ca9f4942SBharata B Rao * 6960f0a643SBharata B Rao * Shared pages: Whenever guest shares a secure page, UV will split and 7060f0a643SBharata B Rao * remap the 2MB page if required and issue H_SVM_PAGE_IN with 64K page size. 7160f0a643SBharata B Rao * 72008e359cSBharata B Rao * HV invalidating a page: When a regular page belonging to secure 73008e359cSBharata B Rao * guest gets unmapped, HV informs UV with UV_PAGE_INVAL of 64K 74008e359cSBharata B Rao * page size. Using 64K page size is correct here because any non-secure 75008e359cSBharata B Rao * page will essentially be of 64K page size. Splitting by UV during sharing 76008e359cSBharata B Rao * and page-out ensures this. 77008e359cSBharata B Rao * 78008e359cSBharata B Rao * Page fault handling: When HV handles page fault of a page belonging 79008e359cSBharata B Rao * to secure guest, it sends that to UV with a 64K UV_PAGE_IN request. 80008e359cSBharata B Rao * Using 64K size is correct here too as UV would have split the 2MB page 81008e359cSBharata B Rao * into 64k mappings and would have done page-outs earlier. 82008e359cSBharata B Rao * 83ca9f4942SBharata B Rao * In summary, the current secure pages handling code in HV assumes 84ca9f4942SBharata B Rao * 64K page size and in fact fails any page-in/page-out requests of 85ca9f4942SBharata B Rao * non-64K size upfront. If and when UV starts supporting multiple 86ca9f4942SBharata B Rao * page-sizes, we need to break this assumption. 87ca9f4942SBharata B Rao */ 88ca9f4942SBharata B Rao 89ca9f4942SBharata B Rao #include <linux/pagemap.h> 90ca9f4942SBharata B Rao #include <linux/migrate.h> 91ca9f4942SBharata B Rao #include <linux/kvm_host.h> 92ca9f4942SBharata B Rao #include <linux/ksm.h> 9313a9a5d1SMarc Zyngier #include <linux/of.h> 94dc90f084SChristoph Hellwig #include <linux/memremap.h> 95ca9f4942SBharata B Rao #include <asm/ultravisor.h> 96ca9f4942SBharata B Rao #include <asm/mman.h> 97ca9f4942SBharata B Rao #include <asm/kvm_ppc.h> 98dfaa973aSRam Pai #include <asm/kvm_book3s_uvmem.h> 99ca9f4942SBharata B Rao 100ca9f4942SBharata B Rao static struct dev_pagemap kvmppc_uvmem_pgmap; 101ca9f4942SBharata B Rao static unsigned long *kvmppc_uvmem_bitmap; 102ca9f4942SBharata B Rao static DEFINE_SPINLOCK(kvmppc_uvmem_bitmap_lock); 103ca9f4942SBharata B Rao 104651a6310SRam Pai /* 105651a6310SRam Pai * States of a GFN 106651a6310SRam Pai * --------------- 107651a6310SRam Pai * The GFN can be in one of the following states. 108651a6310SRam Pai * 109651a6310SRam Pai * (a) Secure - The GFN is secure. The GFN is associated with 110651a6310SRam Pai * a Secure VM, the contents of the GFN is not accessible 111651a6310SRam Pai * to the Hypervisor. This GFN can be backed by a secure-PFN, 112651a6310SRam Pai * or can be backed by a normal-PFN with contents encrypted. 113651a6310SRam Pai * The former is true when the GFN is paged-in into the 114651a6310SRam Pai * ultravisor. The latter is true when the GFN is paged-out 115651a6310SRam Pai * of the ultravisor. 116651a6310SRam Pai * 117651a6310SRam Pai * (b) Shared - The GFN is shared. The GFN is associated with a 118651a6310SRam Pai * a secure VM. The contents of the GFN is accessible to 119651a6310SRam Pai * Hypervisor. This GFN is backed by a normal-PFN and its 120651a6310SRam Pai * content is un-encrypted. 121651a6310SRam Pai * 122651a6310SRam Pai * (c) Normal - The GFN is a normal. The GFN is associated with 123651a6310SRam Pai * a normal VM. The contents of the GFN is accesible to 124651a6310SRam Pai * the Hypervisor. Its content is never encrypted. 125651a6310SRam Pai * 126651a6310SRam Pai * States of a VM. 127651a6310SRam Pai * --------------- 128651a6310SRam Pai * 129651a6310SRam Pai * Normal VM: A VM whose contents are always accessible to 130651a6310SRam Pai * the hypervisor. All its GFNs are normal-GFNs. 131651a6310SRam Pai * 132651a6310SRam Pai * Secure VM: A VM whose contents are not accessible to the 133651a6310SRam Pai * hypervisor without the VM's consent. Its GFNs are 134651a6310SRam Pai * either Shared-GFN or Secure-GFNs. 135651a6310SRam Pai * 136651a6310SRam Pai * Transient VM: A Normal VM that is transitioning to secure VM. 137651a6310SRam Pai * The transition starts on successful return of 138651a6310SRam Pai * H_SVM_INIT_START, and ends on successful return 139651a6310SRam Pai * of H_SVM_INIT_DONE. This transient VM, can have GFNs 140651a6310SRam Pai * in any of the three states; i.e Secure-GFN, Shared-GFN, 141651a6310SRam Pai * and Normal-GFN. The VM never executes in this state 142651a6310SRam Pai * in supervisor-mode. 143651a6310SRam Pai * 144651a6310SRam Pai * Memory slot State. 145651a6310SRam Pai * ----------------------------- 146651a6310SRam Pai * The state of a memory slot mirrors the state of the 147651a6310SRam Pai * VM the memory slot is associated with. 148651a6310SRam Pai * 149651a6310SRam Pai * VM State transition. 150651a6310SRam Pai * -------------------- 151651a6310SRam Pai * 152651a6310SRam Pai * A VM always starts in Normal Mode. 153651a6310SRam Pai * 154651a6310SRam Pai * H_SVM_INIT_START moves the VM into transient state. During this 155651a6310SRam Pai * time the Ultravisor may request some of its GFNs to be shared or 156651a6310SRam Pai * secured. So its GFNs can be in one of the three GFN states. 157651a6310SRam Pai * 158651a6310SRam Pai * H_SVM_INIT_DONE moves the VM entirely from transient state to 159651a6310SRam Pai * secure-state. At this point any left-over normal-GFNs are 160651a6310SRam Pai * transitioned to Secure-GFN. 161651a6310SRam Pai * 162651a6310SRam Pai * H_SVM_INIT_ABORT moves the transient VM back to normal VM. 163651a6310SRam Pai * All its GFNs are moved to Normal-GFNs. 164651a6310SRam Pai * 165651a6310SRam Pai * UV_TERMINATE transitions the secure-VM back to normal-VM. All 166651a6310SRam Pai * the secure-GFN and shared-GFNs are tranistioned to normal-GFN 167651a6310SRam Pai * Note: The contents of the normal-GFN is undefined at this point. 168651a6310SRam Pai * 169651a6310SRam Pai * GFN state implementation: 170651a6310SRam Pai * ------------------------- 171651a6310SRam Pai * 172651a6310SRam Pai * Secure GFN is associated with a secure-PFN; also called uvmem_pfn, 173651a6310SRam Pai * when the GFN is paged-in. Its pfn[] has KVMPPC_GFN_UVMEM_PFN flag 174651a6310SRam Pai * set, and contains the value of the secure-PFN. 175651a6310SRam Pai * It is associated with a normal-PFN; also called mem_pfn, when 176651a6310SRam Pai * the GFN is pagedout. Its pfn[] has KVMPPC_GFN_MEM_PFN flag set. 177651a6310SRam Pai * The value of the normal-PFN is not tracked. 178651a6310SRam Pai * 179651a6310SRam Pai * Shared GFN is associated with a normal-PFN. Its pfn[] has 180651a6310SRam Pai * KVMPPC_UVMEM_SHARED_PFN flag set. The value of the normal-PFN 181651a6310SRam Pai * is not tracked. 182651a6310SRam Pai * 183651a6310SRam Pai * Normal GFN is associated with normal-PFN. Its pfn[] has 184651a6310SRam Pai * no flag set. The value of the normal-PFN is not tracked. 185651a6310SRam Pai * 186651a6310SRam Pai * Life cycle of a GFN 187651a6310SRam Pai * -------------------- 188651a6310SRam Pai * 189651a6310SRam Pai * -------------------------------------------------------------- 190651a6310SRam Pai * | | Share | Unshare | SVM |H_SVM_INIT_DONE| 191651a6310SRam Pai * | |operation |operation | abort/ | | 192651a6310SRam Pai * | | | | terminate | | 193651a6310SRam Pai * ------------------------------------------------------------- 194651a6310SRam Pai * | | | | | | 195651a6310SRam Pai * | Secure | Shared | Secure |Normal |Secure | 196651a6310SRam Pai * | | | | | | 197651a6310SRam Pai * | Shared | Shared | Secure |Normal |Shared | 198651a6310SRam Pai * | | | | | | 199651a6310SRam Pai * | Normal | Shared | Secure |Normal |Secure | 200651a6310SRam Pai * -------------------------------------------------------------- 201651a6310SRam Pai * 202651a6310SRam Pai * Life cycle of a VM 203651a6310SRam Pai * -------------------- 204651a6310SRam Pai * 205651a6310SRam Pai * -------------------------------------------------------------------- 206651a6310SRam Pai * | | start | H_SVM_ |H_SVM_ |H_SVM_ |UV_SVM_ | 207651a6310SRam Pai * | | VM |INIT_START|INIT_DONE|INIT_ABORT |TERMINATE | 208651a6310SRam Pai * | | | | | | | 209651a6310SRam Pai * --------- ---------------------------------------------------------- 210651a6310SRam Pai * | | | | | | | 211651a6310SRam Pai * | Normal | Normal | Transient|Error |Error |Normal | 212651a6310SRam Pai * | | | | | | | 213651a6310SRam Pai * | Secure | Error | Error |Error |Error |Normal | 214651a6310SRam Pai * | | | | | | | 215651a6310SRam Pai * |Transient| N/A | Error |Secure |Normal |Normal | 216651a6310SRam Pai * -------------------------------------------------------------------- 217651a6310SRam Pai */ 218651a6310SRam Pai 219651a6310SRam Pai #define KVMPPC_GFN_UVMEM_PFN (1UL << 63) 220651a6310SRam Pai #define KVMPPC_GFN_MEM_PFN (1UL << 62) 221651a6310SRam Pai #define KVMPPC_GFN_SHARED (1UL << 61) 222651a6310SRam Pai #define KVMPPC_GFN_SECURE (KVMPPC_GFN_UVMEM_PFN | KVMPPC_GFN_MEM_PFN) 223651a6310SRam Pai #define KVMPPC_GFN_FLAG_MASK (KVMPPC_GFN_SECURE | KVMPPC_GFN_SHARED) 224651a6310SRam Pai #define KVMPPC_GFN_PFN_MASK (~KVMPPC_GFN_FLAG_MASK) 225ca9f4942SBharata B Rao 226ca9f4942SBharata B Rao struct kvmppc_uvmem_slot { 227ca9f4942SBharata B Rao struct list_head list; 228ca9f4942SBharata B Rao unsigned long nr_pfns; 229ca9f4942SBharata B Rao unsigned long base_pfn; 230ca9f4942SBharata B Rao unsigned long *pfns; 231ca9f4942SBharata B Rao }; 232ca9f4942SBharata B Rao struct kvmppc_uvmem_page_pvt { 233ca9f4942SBharata B Rao struct kvm *kvm; 234ca9f4942SBharata B Rao unsigned long gpa; 23560f0a643SBharata B Rao bool skip_page_out; 236651a6310SRam Pai bool remove_gfn; 237ca9f4942SBharata B Rao }; 238ca9f4942SBharata B Rao 2399a5788c6SPaul Mackerras bool kvmppc_uvmem_available(void) 2409a5788c6SPaul Mackerras { 2419a5788c6SPaul Mackerras /* 2429a5788c6SPaul Mackerras * If kvmppc_uvmem_bitmap != NULL, then there is an ultravisor 2439a5788c6SPaul Mackerras * and our data structures have been initialized successfully. 2449a5788c6SPaul Mackerras */ 2459a5788c6SPaul Mackerras return !!kvmppc_uvmem_bitmap; 2469a5788c6SPaul Mackerras } 2479a5788c6SPaul Mackerras 248ca9f4942SBharata B Rao int kvmppc_uvmem_slot_init(struct kvm *kvm, const struct kvm_memory_slot *slot) 249ca9f4942SBharata B Rao { 250ca9f4942SBharata B Rao struct kvmppc_uvmem_slot *p; 251ca9f4942SBharata B Rao 252ca9f4942SBharata B Rao p = kzalloc(sizeof(*p), GFP_KERNEL); 253ca9f4942SBharata B Rao if (!p) 254ca9f4942SBharata B Rao return -ENOMEM; 25537b2a651SPaolo Bonzini p->pfns = vcalloc(slot->npages, sizeof(*p->pfns)); 256ca9f4942SBharata B Rao if (!p->pfns) { 257ca9f4942SBharata B Rao kfree(p); 258ca9f4942SBharata B Rao return -ENOMEM; 259ca9f4942SBharata B Rao } 260ca9f4942SBharata B Rao p->nr_pfns = slot->npages; 261ca9f4942SBharata B Rao p->base_pfn = slot->base_gfn; 262ca9f4942SBharata B Rao 263ca9f4942SBharata B Rao mutex_lock(&kvm->arch.uvmem_lock); 264ca9f4942SBharata B Rao list_add(&p->list, &kvm->arch.uvmem_pfns); 265ca9f4942SBharata B Rao mutex_unlock(&kvm->arch.uvmem_lock); 266ca9f4942SBharata B Rao 267ca9f4942SBharata B Rao return 0; 268ca9f4942SBharata B Rao } 269ca9f4942SBharata B Rao 270ca9f4942SBharata B Rao /* 271ca9f4942SBharata B Rao * All device PFNs are already released by the time we come here. 272ca9f4942SBharata B Rao */ 273ca9f4942SBharata B Rao void kvmppc_uvmem_slot_free(struct kvm *kvm, const struct kvm_memory_slot *slot) 274ca9f4942SBharata B Rao { 275ca9f4942SBharata B Rao struct kvmppc_uvmem_slot *p, *next; 276ca9f4942SBharata B Rao 277ca9f4942SBharata B Rao mutex_lock(&kvm->arch.uvmem_lock); 278ca9f4942SBharata B Rao list_for_each_entry_safe(p, next, &kvm->arch.uvmem_pfns, list) { 279ca9f4942SBharata B Rao if (p->base_pfn == slot->base_gfn) { 280ca9f4942SBharata B Rao vfree(p->pfns); 281ca9f4942SBharata B Rao list_del(&p->list); 282ca9f4942SBharata B Rao kfree(p); 283ca9f4942SBharata B Rao break; 284ca9f4942SBharata B Rao } 285ca9f4942SBharata B Rao } 286ca9f4942SBharata B Rao mutex_unlock(&kvm->arch.uvmem_lock); 287ca9f4942SBharata B Rao } 288ca9f4942SBharata B Rao 289651a6310SRam Pai static void kvmppc_mark_gfn(unsigned long gfn, struct kvm *kvm, 290651a6310SRam Pai unsigned long flag, unsigned long uvmem_pfn) 291ca9f4942SBharata B Rao { 292ca9f4942SBharata B Rao struct kvmppc_uvmem_slot *p; 293ca9f4942SBharata B Rao 294ca9f4942SBharata B Rao list_for_each_entry(p, &kvm->arch.uvmem_pfns, list) { 295ca9f4942SBharata B Rao if (gfn >= p->base_pfn && gfn < p->base_pfn + p->nr_pfns) { 296ca9f4942SBharata B Rao unsigned long index = gfn - p->base_pfn; 297ca9f4942SBharata B Rao 298651a6310SRam Pai if (flag == KVMPPC_GFN_UVMEM_PFN) 299651a6310SRam Pai p->pfns[index] = uvmem_pfn | flag; 300651a6310SRam Pai else 301651a6310SRam Pai p->pfns[index] = flag; 302ca9f4942SBharata B Rao return; 303ca9f4942SBharata B Rao } 304ca9f4942SBharata B Rao } 305ca9f4942SBharata B Rao } 306ca9f4942SBharata B Rao 307651a6310SRam Pai /* mark the GFN as secure-GFN associated with @uvmem pfn device-PFN. */ 308651a6310SRam Pai static void kvmppc_gfn_secure_uvmem_pfn(unsigned long gfn, 309651a6310SRam Pai unsigned long uvmem_pfn, struct kvm *kvm) 310ca9f4942SBharata B Rao { 311651a6310SRam Pai kvmppc_mark_gfn(gfn, kvm, KVMPPC_GFN_UVMEM_PFN, uvmem_pfn); 312ca9f4942SBharata B Rao } 313ca9f4942SBharata B Rao 314651a6310SRam Pai /* mark the GFN as secure-GFN associated with a memory-PFN. */ 315651a6310SRam Pai static void kvmppc_gfn_secure_mem_pfn(unsigned long gfn, struct kvm *kvm) 316651a6310SRam Pai { 317651a6310SRam Pai kvmppc_mark_gfn(gfn, kvm, KVMPPC_GFN_MEM_PFN, 0); 318651a6310SRam Pai } 319651a6310SRam Pai 320651a6310SRam Pai /* mark the GFN as a shared GFN. */ 321651a6310SRam Pai static void kvmppc_gfn_shared(unsigned long gfn, struct kvm *kvm) 322651a6310SRam Pai { 323651a6310SRam Pai kvmppc_mark_gfn(gfn, kvm, KVMPPC_GFN_SHARED, 0); 324651a6310SRam Pai } 325651a6310SRam Pai 326651a6310SRam Pai /* mark the GFN as a non-existent GFN. */ 327651a6310SRam Pai static void kvmppc_gfn_remove(unsigned long gfn, struct kvm *kvm) 328651a6310SRam Pai { 329651a6310SRam Pai kvmppc_mark_gfn(gfn, kvm, 0, 0); 330651a6310SRam Pai } 331651a6310SRam Pai 332651a6310SRam Pai /* return true, if the GFN is a secure-GFN backed by a secure-PFN */ 333ca9f4942SBharata B Rao static bool kvmppc_gfn_is_uvmem_pfn(unsigned long gfn, struct kvm *kvm, 334ca9f4942SBharata B Rao unsigned long *uvmem_pfn) 335ca9f4942SBharata B Rao { 336ca9f4942SBharata B Rao struct kvmppc_uvmem_slot *p; 337ca9f4942SBharata B Rao 338ca9f4942SBharata B Rao list_for_each_entry(p, &kvm->arch.uvmem_pfns, list) { 339ca9f4942SBharata B Rao if (gfn >= p->base_pfn && gfn < p->base_pfn + p->nr_pfns) { 340ca9f4942SBharata B Rao unsigned long index = gfn - p->base_pfn; 341ca9f4942SBharata B Rao 342651a6310SRam Pai if (p->pfns[index] & KVMPPC_GFN_UVMEM_PFN) { 343ca9f4942SBharata B Rao if (uvmem_pfn) 344ca9f4942SBharata B Rao *uvmem_pfn = p->pfns[index] & 345651a6310SRam Pai KVMPPC_GFN_PFN_MASK; 346ca9f4942SBharata B Rao return true; 347ca9f4942SBharata B Rao } else 348ca9f4942SBharata B Rao return false; 349ca9f4942SBharata B Rao } 350ca9f4942SBharata B Rao } 351ca9f4942SBharata B Rao return false; 352ca9f4942SBharata B Rao } 353ca9f4942SBharata B Rao 354dfaa973aSRam Pai /* 355dfaa973aSRam Pai * starting from *gfn search for the next available GFN that is not yet 356dfaa973aSRam Pai * transitioned to a secure GFN. return the value of that GFN in *gfn. If a 357dfaa973aSRam Pai * GFN is found, return true, else return false 358dfaa973aSRam Pai * 359dfaa973aSRam Pai * Must be called with kvm->arch.uvmem_lock held. 360dfaa973aSRam Pai */ 361dfaa973aSRam Pai static bool kvmppc_next_nontransitioned_gfn(const struct kvm_memory_slot *memslot, 362dfaa973aSRam Pai struct kvm *kvm, unsigned long *gfn) 363dfaa973aSRam Pai { 364*300981abSXiaomeng Tong struct kvmppc_uvmem_slot *p = NULL, *iter; 365dfaa973aSRam Pai bool ret = false; 366dfaa973aSRam Pai unsigned long i; 367dfaa973aSRam Pai 368*300981abSXiaomeng Tong list_for_each_entry(iter, &kvm->arch.uvmem_pfns, list) 369*300981abSXiaomeng Tong if (*gfn >= iter->base_pfn && *gfn < iter->base_pfn + iter->nr_pfns) { 370*300981abSXiaomeng Tong p = iter; 371dfaa973aSRam Pai break; 372*300981abSXiaomeng Tong } 373dfaa973aSRam Pai if (!p) 374dfaa973aSRam Pai return ret; 375dfaa973aSRam Pai /* 376dfaa973aSRam Pai * The code below assumes, one to one correspondence between 377dfaa973aSRam Pai * kvmppc_uvmem_slot and memslot. 378dfaa973aSRam Pai */ 379dfaa973aSRam Pai for (i = *gfn; i < p->base_pfn + p->nr_pfns; i++) { 380dfaa973aSRam Pai unsigned long index = i - p->base_pfn; 381dfaa973aSRam Pai 382dfaa973aSRam Pai if (!(p->pfns[index] & KVMPPC_GFN_FLAG_MASK)) { 383dfaa973aSRam Pai *gfn = i; 384dfaa973aSRam Pai ret = true; 385dfaa973aSRam Pai break; 386dfaa973aSRam Pai } 387dfaa973aSRam Pai } 388dfaa973aSRam Pai return ret; 389dfaa973aSRam Pai } 390dfaa973aSRam Pai 3912027a24aSRam Pai static int kvmppc_memslot_page_merge(struct kvm *kvm, 3922027a24aSRam Pai const struct kvm_memory_slot *memslot, bool merge) 3932027a24aSRam Pai { 3942027a24aSRam Pai unsigned long gfn = memslot->base_gfn; 3952027a24aSRam Pai unsigned long end, start = gfn_to_hva(kvm, gfn); 3962027a24aSRam Pai int ret = 0; 3972027a24aSRam Pai struct vm_area_struct *vma; 3982027a24aSRam Pai int merge_flag = (merge) ? MADV_MERGEABLE : MADV_UNMERGEABLE; 3992027a24aSRam Pai 4002027a24aSRam Pai if (kvm_is_error_hva(start)) 4012027a24aSRam Pai return H_STATE; 4022027a24aSRam Pai 4032027a24aSRam Pai end = start + (memslot->npages << PAGE_SHIFT); 4042027a24aSRam Pai 4052027a24aSRam Pai mmap_write_lock(kvm->mm); 4062027a24aSRam Pai do { 4072027a24aSRam Pai vma = find_vma_intersection(kvm->mm, start, end); 4082027a24aSRam Pai if (!vma) { 4092027a24aSRam Pai ret = H_STATE; 4102027a24aSRam Pai break; 4112027a24aSRam Pai } 4122027a24aSRam Pai ret = ksm_madvise(vma, vma->vm_start, vma->vm_end, 4132027a24aSRam Pai merge_flag, &vma->vm_flags); 4142027a24aSRam Pai if (ret) { 4152027a24aSRam Pai ret = H_STATE; 4162027a24aSRam Pai break; 4172027a24aSRam Pai } 4182027a24aSRam Pai start = vma->vm_end; 4192027a24aSRam Pai } while (end > vma->vm_end); 4202027a24aSRam Pai 4212027a24aSRam Pai mmap_write_unlock(kvm->mm); 4222027a24aSRam Pai return ret; 4232027a24aSRam Pai } 4242027a24aSRam Pai 425a2ce7200SLaurent Dufour static void __kvmppc_uvmem_memslot_delete(struct kvm *kvm, 4262027a24aSRam Pai const struct kvm_memory_slot *memslot) 4272027a24aSRam Pai { 4282027a24aSRam Pai uv_unregister_mem_slot(kvm->arch.lpid, memslot->id); 4292027a24aSRam Pai kvmppc_uvmem_slot_free(kvm, memslot); 4302027a24aSRam Pai kvmppc_memslot_page_merge(kvm, memslot, true); 4312027a24aSRam Pai } 4322027a24aSRam Pai 433a2ce7200SLaurent Dufour static int __kvmppc_uvmem_memslot_create(struct kvm *kvm, 4342027a24aSRam Pai const struct kvm_memory_slot *memslot) 4352027a24aSRam Pai { 4362027a24aSRam Pai int ret = H_PARAMETER; 4372027a24aSRam Pai 4382027a24aSRam Pai if (kvmppc_memslot_page_merge(kvm, memslot, false)) 4392027a24aSRam Pai return ret; 4402027a24aSRam Pai 4412027a24aSRam Pai if (kvmppc_uvmem_slot_init(kvm, memslot)) 4422027a24aSRam Pai goto out1; 4432027a24aSRam Pai 4442027a24aSRam Pai ret = uv_register_mem_slot(kvm->arch.lpid, 4452027a24aSRam Pai memslot->base_gfn << PAGE_SHIFT, 4462027a24aSRam Pai memslot->npages * PAGE_SIZE, 4472027a24aSRam Pai 0, memslot->id); 4482027a24aSRam Pai if (ret < 0) { 4492027a24aSRam Pai ret = H_PARAMETER; 4502027a24aSRam Pai goto out; 4512027a24aSRam Pai } 4522027a24aSRam Pai return 0; 4532027a24aSRam Pai out: 4542027a24aSRam Pai kvmppc_uvmem_slot_free(kvm, memslot); 4552027a24aSRam Pai out1: 4562027a24aSRam Pai kvmppc_memslot_page_merge(kvm, memslot, true); 4572027a24aSRam Pai return ret; 4582027a24aSRam Pai } 4592027a24aSRam Pai 460ca9f4942SBharata B Rao unsigned long kvmppc_h_svm_init_start(struct kvm *kvm) 461ca9f4942SBharata B Rao { 462ca9f4942SBharata B Rao struct kvm_memslots *slots; 4632027a24aSRam Pai struct kvm_memory_slot *memslot, *m; 464ca9f4942SBharata B Rao int ret = H_SUCCESS; 465a54d8066SMaciej S. Szmigiero int srcu_idx, bkt; 466ca9f4942SBharata B Rao 467377f02d4SLaurent Dufour kvm->arch.secure_guest = KVMPPC_SECURE_INIT_START; 468377f02d4SLaurent Dufour 469ca9f4942SBharata B Rao if (!kvmppc_uvmem_bitmap) 470ca9f4942SBharata B Rao return H_UNSUPPORTED; 471ca9f4942SBharata B Rao 472ca9f4942SBharata B Rao /* Only radix guests can be secure guests */ 473ca9f4942SBharata B Rao if (!kvm_is_radix(kvm)) 474ca9f4942SBharata B Rao return H_UNSUPPORTED; 475ca9f4942SBharata B Rao 4769a5788c6SPaul Mackerras /* NAK the transition to secure if not enabled */ 4779a5788c6SPaul Mackerras if (!kvm->arch.svm_enabled) 4789a5788c6SPaul Mackerras return H_AUTHORITY; 4799a5788c6SPaul Mackerras 480ca9f4942SBharata B Rao srcu_idx = srcu_read_lock(&kvm->srcu); 4812027a24aSRam Pai 4822027a24aSRam Pai /* register the memslot */ 483ca9f4942SBharata B Rao slots = kvm_memslots(kvm); 484a54d8066SMaciej S. Szmigiero kvm_for_each_memslot(memslot, bkt, slots) { 485a2ce7200SLaurent Dufour ret = __kvmppc_uvmem_memslot_create(kvm, memslot); 4862027a24aSRam Pai if (ret) 4872027a24aSRam Pai break; 488ca9f4942SBharata B Rao } 4892027a24aSRam Pai 4902027a24aSRam Pai if (ret) { 4912027a24aSRam Pai slots = kvm_memslots(kvm); 492a54d8066SMaciej S. Szmigiero kvm_for_each_memslot(m, bkt, slots) { 4932027a24aSRam Pai if (m == memslot) 4942027a24aSRam Pai break; 495a2ce7200SLaurent Dufour __kvmppc_uvmem_memslot_delete(kvm, memslot); 496ca9f4942SBharata B Rao } 497ca9f4942SBharata B Rao } 4982027a24aSRam Pai 499ca9f4942SBharata B Rao srcu_read_unlock(&kvm->srcu, srcu_idx); 500ca9f4942SBharata B Rao return ret; 501ca9f4942SBharata B Rao } 502ca9f4942SBharata B Rao 503ca9f4942SBharata B Rao /* 504f1b87ea8SLaurent Dufour * Provision a new page on HV side and copy over the contents 505f1b87ea8SLaurent Dufour * from secure memory using UV_PAGE_OUT uvcall. 506f1b87ea8SLaurent Dufour * Caller must held kvm->arch.uvmem_lock. 507f1b87ea8SLaurent Dufour */ 508f1b87ea8SLaurent Dufour static int __kvmppc_svm_page_out(struct vm_area_struct *vma, 509f1b87ea8SLaurent Dufour unsigned long start, 510f1b87ea8SLaurent Dufour unsigned long end, unsigned long page_shift, 511f1b87ea8SLaurent Dufour struct kvm *kvm, unsigned long gpa) 512ca9f4942SBharata B Rao { 513f1b87ea8SLaurent Dufour unsigned long src_pfn, dst_pfn = 0; 514f1b87ea8SLaurent Dufour struct migrate_vma mig; 515f1b87ea8SLaurent Dufour struct page *dpage, *spage; 516f1b87ea8SLaurent Dufour struct kvmppc_uvmem_page_pvt *pvt; 517f1b87ea8SLaurent Dufour unsigned long pfn; 518f1b87ea8SLaurent Dufour int ret = U_SUCCESS; 519ca9f4942SBharata B Rao 520f1b87ea8SLaurent Dufour memset(&mig, 0, sizeof(mig)); 521f1b87ea8SLaurent Dufour mig.vma = vma; 522f1b87ea8SLaurent Dufour mig.start = start; 523f1b87ea8SLaurent Dufour mig.end = end; 524f1b87ea8SLaurent Dufour mig.src = &src_pfn; 525f1b87ea8SLaurent Dufour mig.dst = &dst_pfn; 5263ff03278SPaolo Bonzini mig.pgmap_owner = &kvmppc_uvmem_pgmap; 5273ff03278SPaolo Bonzini mig.flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE; 528f1b87ea8SLaurent Dufour 529f1b87ea8SLaurent Dufour /* The requested page is already paged-out, nothing to do */ 530f1b87ea8SLaurent Dufour if (!kvmppc_gfn_is_uvmem_pfn(gpa >> page_shift, kvm, NULL)) 531f1b87ea8SLaurent Dufour return ret; 532f1b87ea8SLaurent Dufour 533f1b87ea8SLaurent Dufour ret = migrate_vma_setup(&mig); 534f1b87ea8SLaurent Dufour if (ret) 535f1b87ea8SLaurent Dufour return -1; 536f1b87ea8SLaurent Dufour 537f1b87ea8SLaurent Dufour spage = migrate_pfn_to_page(*mig.src); 538f1b87ea8SLaurent Dufour if (!spage || !(*mig.src & MIGRATE_PFN_MIGRATE)) 539f1b87ea8SLaurent Dufour goto out_finalize; 540f1b87ea8SLaurent Dufour 541f1b87ea8SLaurent Dufour if (!is_zone_device_page(spage)) 542f1b87ea8SLaurent Dufour goto out_finalize; 543f1b87ea8SLaurent Dufour 544f1b87ea8SLaurent Dufour dpage = alloc_page_vma(GFP_HIGHUSER, vma, start); 545f1b87ea8SLaurent Dufour if (!dpage) { 546f1b87ea8SLaurent Dufour ret = -1; 547f1b87ea8SLaurent Dufour goto out_finalize; 548f1b87ea8SLaurent Dufour } 549f1b87ea8SLaurent Dufour 550f1b87ea8SLaurent Dufour lock_page(dpage); 551f1b87ea8SLaurent Dufour pvt = spage->zone_device_data; 552f1b87ea8SLaurent Dufour pfn = page_to_pfn(dpage); 553f1b87ea8SLaurent Dufour 554f1b87ea8SLaurent Dufour /* 555f1b87ea8SLaurent Dufour * This function is used in two cases: 556f1b87ea8SLaurent Dufour * - When HV touches a secure page, for which we do UV_PAGE_OUT 557f1b87ea8SLaurent Dufour * - When a secure page is converted to shared page, we *get* 558f1b87ea8SLaurent Dufour * the page to essentially unmap the device page. In this 559f1b87ea8SLaurent Dufour * case we skip page-out. 560f1b87ea8SLaurent Dufour */ 561f1b87ea8SLaurent Dufour if (!pvt->skip_page_out) 562f1b87ea8SLaurent Dufour ret = uv_page_out(kvm->arch.lpid, pfn << page_shift, 563f1b87ea8SLaurent Dufour gpa, 0, page_shift); 564f1b87ea8SLaurent Dufour 565f1b87ea8SLaurent Dufour if (ret == U_SUCCESS) 566ab09243aSAlistair Popple *mig.dst = migrate_pfn(pfn); 567f1b87ea8SLaurent Dufour else { 568f1b87ea8SLaurent Dufour unlock_page(dpage); 569f1b87ea8SLaurent Dufour __free_page(dpage); 570f1b87ea8SLaurent Dufour goto out_finalize; 571f1b87ea8SLaurent Dufour } 572f1b87ea8SLaurent Dufour 573f1b87ea8SLaurent Dufour migrate_vma_pages(&mig); 574f1b87ea8SLaurent Dufour 575f1b87ea8SLaurent Dufour out_finalize: 576f1b87ea8SLaurent Dufour migrate_vma_finalize(&mig); 577f1b87ea8SLaurent Dufour return ret; 578f1b87ea8SLaurent Dufour } 579f1b87ea8SLaurent Dufour 580f1b87ea8SLaurent Dufour static inline int kvmppc_svm_page_out(struct vm_area_struct *vma, 581f1b87ea8SLaurent Dufour unsigned long start, unsigned long end, 582f1b87ea8SLaurent Dufour unsigned long page_shift, 583f1b87ea8SLaurent Dufour struct kvm *kvm, unsigned long gpa) 584f1b87ea8SLaurent Dufour { 585f1b87ea8SLaurent Dufour int ret; 586f1b87ea8SLaurent Dufour 587f1b87ea8SLaurent Dufour mutex_lock(&kvm->arch.uvmem_lock); 588f1b87ea8SLaurent Dufour ret = __kvmppc_svm_page_out(vma, start, end, page_shift, kvm, gpa); 589f1b87ea8SLaurent Dufour mutex_unlock(&kvm->arch.uvmem_lock); 590f1b87ea8SLaurent Dufour 591f1b87ea8SLaurent Dufour return ret; 592ca9f4942SBharata B Rao } 593ca9f4942SBharata B Rao 594ca9f4942SBharata B Rao /* 595c3262257SBharata B Rao * Drop device pages that we maintain for the secure guest 596c3262257SBharata B Rao * 597c3262257SBharata B Rao * We first mark the pages to be skipped from UV_PAGE_OUT when there 598c3262257SBharata B Rao * is HV side fault on these pages. Next we *get* these pages, forcing 599c3262257SBharata B Rao * fault on them, do fault time migration to replace the device PTEs in 600c3262257SBharata B Rao * QEMU page table with normal PTEs from newly allocated pages. 601c3262257SBharata B Rao */ 60281ab595dSLaurent Dufour void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *slot, 603ce477a7aSSukadev Bhattiprolu struct kvm *kvm, bool skip_page_out) 604c3262257SBharata B Rao { 605c3262257SBharata B Rao int i; 606c3262257SBharata B Rao struct kvmppc_uvmem_page_pvt *pvt; 607c3262257SBharata B Rao struct page *uvmem_page; 60881ab595dSLaurent Dufour struct vm_area_struct *vma = NULL; 60981ab595dSLaurent Dufour unsigned long uvmem_pfn, gfn; 61081ab595dSLaurent Dufour unsigned long addr; 611c3262257SBharata B Rao 61281ab595dSLaurent Dufour mmap_read_lock(kvm->mm); 61381ab595dSLaurent Dufour 61481ab595dSLaurent Dufour addr = slot->userspace_addr; 61581ab595dSLaurent Dufour 61681ab595dSLaurent Dufour gfn = slot->base_gfn; 61781ab595dSLaurent Dufour for (i = slot->npages; i; --i, ++gfn, addr += PAGE_SIZE) { 61881ab595dSLaurent Dufour 61981ab595dSLaurent Dufour /* Fetch the VMA if addr is not in the latest fetched one */ 62081ab595dSLaurent Dufour if (!vma || addr >= vma->vm_end) { 62127a14d28SLiam Howlett vma = vma_lookup(kvm->mm, addr); 62281ab595dSLaurent Dufour if (!vma) { 62381ab595dSLaurent Dufour pr_err("Can't find VMA for gfn:0x%lx\n", gfn); 62481ab595dSLaurent Dufour break; 62581ab595dSLaurent Dufour } 626c3262257SBharata B Rao } 627c3262257SBharata B Rao 62881ab595dSLaurent Dufour mutex_lock(&kvm->arch.uvmem_lock); 62981ab595dSLaurent Dufour 63081ab595dSLaurent Dufour if (kvmppc_gfn_is_uvmem_pfn(gfn, kvm, &uvmem_pfn)) { 631c3262257SBharata B Rao uvmem_page = pfn_to_page(uvmem_pfn); 632c3262257SBharata B Rao pvt = uvmem_page->zone_device_data; 633ce477a7aSSukadev Bhattiprolu pvt->skip_page_out = skip_page_out; 634651a6310SRam Pai pvt->remove_gfn = true; 635c3262257SBharata B Rao 63681ab595dSLaurent Dufour if (__kvmppc_svm_page_out(vma, addr, addr + PAGE_SIZE, 63781ab595dSLaurent Dufour PAGE_SHIFT, kvm, pvt->gpa)) 63881ab595dSLaurent Dufour pr_err("Can't page out gpa:0x%lx addr:0x%lx\n", 63981ab595dSLaurent Dufour pvt->gpa, addr); 64081ab595dSLaurent Dufour } else { 64181ab595dSLaurent Dufour /* Remove the shared flag if any */ 64281ab595dSLaurent Dufour kvmppc_gfn_remove(gfn, kvm); 643c3262257SBharata B Rao } 64481ab595dSLaurent Dufour 64581ab595dSLaurent Dufour mutex_unlock(&kvm->arch.uvmem_lock); 64681ab595dSLaurent Dufour } 64781ab595dSLaurent Dufour 64881ab595dSLaurent Dufour mmap_read_unlock(kvm->mm); 649c3262257SBharata B Rao } 650c3262257SBharata B Rao 6513a43970dSSukadev Bhattiprolu unsigned long kvmppc_h_svm_init_abort(struct kvm *kvm) 6523a43970dSSukadev Bhattiprolu { 653a54d8066SMaciej S. Szmigiero int srcu_idx, bkt; 6543a43970dSSukadev Bhattiprolu struct kvm_memory_slot *memslot; 6553a43970dSSukadev Bhattiprolu 6563a43970dSSukadev Bhattiprolu /* 6573a43970dSSukadev Bhattiprolu * Expect to be called only after INIT_START and before INIT_DONE. 6583a43970dSSukadev Bhattiprolu * If INIT_DONE was completed, use normal VM termination sequence. 6593a43970dSSukadev Bhattiprolu */ 6603a43970dSSukadev Bhattiprolu if (!(kvm->arch.secure_guest & KVMPPC_SECURE_INIT_START)) 6613a43970dSSukadev Bhattiprolu return H_UNSUPPORTED; 6623a43970dSSukadev Bhattiprolu 6633a43970dSSukadev Bhattiprolu if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE) 6643a43970dSSukadev Bhattiprolu return H_STATE; 6653a43970dSSukadev Bhattiprolu 6663a43970dSSukadev Bhattiprolu srcu_idx = srcu_read_lock(&kvm->srcu); 6673a43970dSSukadev Bhattiprolu 668a54d8066SMaciej S. Szmigiero kvm_for_each_memslot(memslot, bkt, kvm_memslots(kvm)) 6693a43970dSSukadev Bhattiprolu kvmppc_uvmem_drop_pages(memslot, kvm, false); 6703a43970dSSukadev Bhattiprolu 6713a43970dSSukadev Bhattiprolu srcu_read_unlock(&kvm->srcu, srcu_idx); 6723a43970dSSukadev Bhattiprolu 6733a43970dSSukadev Bhattiprolu kvm->arch.secure_guest = 0; 6743a43970dSSukadev Bhattiprolu uv_svm_terminate(kvm->arch.lpid); 6753a43970dSSukadev Bhattiprolu 6763a43970dSSukadev Bhattiprolu return H_PARAMETER; 6773a43970dSSukadev Bhattiprolu } 6783a43970dSSukadev Bhattiprolu 679c3262257SBharata B Rao /* 680ca9f4942SBharata B Rao * Get a free device PFN from the pool 681ca9f4942SBharata B Rao * 682ca9f4942SBharata B Rao * Called when a normal page is moved to secure memory (UV_PAGE_IN). Device 683ca9f4942SBharata B Rao * PFN will be used to keep track of the secure page on HV side. 684ca9f4942SBharata B Rao * 685ca9f4942SBharata B Rao * Called with kvm->arch.uvmem_lock held 686ca9f4942SBharata B Rao */ 687ca9f4942SBharata B Rao static struct page *kvmppc_uvmem_get_page(unsigned long gpa, struct kvm *kvm) 688ca9f4942SBharata B Rao { 689ca9f4942SBharata B Rao struct page *dpage = NULL; 690ca9f4942SBharata B Rao unsigned long bit, uvmem_pfn; 691ca9f4942SBharata B Rao struct kvmppc_uvmem_page_pvt *pvt; 692ca9f4942SBharata B Rao unsigned long pfn_last, pfn_first; 693ca9f4942SBharata B Rao 694a4574f63SDan Williams pfn_first = kvmppc_uvmem_pgmap.range.start >> PAGE_SHIFT; 695ca9f4942SBharata B Rao pfn_last = pfn_first + 696a4574f63SDan Williams (range_len(&kvmppc_uvmem_pgmap.range) >> PAGE_SHIFT); 697ca9f4942SBharata B Rao 698ca9f4942SBharata B Rao spin_lock(&kvmppc_uvmem_bitmap_lock); 699ca9f4942SBharata B Rao bit = find_first_zero_bit(kvmppc_uvmem_bitmap, 700ca9f4942SBharata B Rao pfn_last - pfn_first); 701ca9f4942SBharata B Rao if (bit >= (pfn_last - pfn_first)) 702ca9f4942SBharata B Rao goto out; 703ca9f4942SBharata B Rao bitmap_set(kvmppc_uvmem_bitmap, bit, 1); 704ca9f4942SBharata B Rao spin_unlock(&kvmppc_uvmem_bitmap_lock); 705ca9f4942SBharata B Rao 706ca9f4942SBharata B Rao pvt = kzalloc(sizeof(*pvt), GFP_KERNEL); 707ca9f4942SBharata B Rao if (!pvt) 708ca9f4942SBharata B Rao goto out_clear; 709ca9f4942SBharata B Rao 710ca9f4942SBharata B Rao uvmem_pfn = bit + pfn_first; 711651a6310SRam Pai kvmppc_gfn_secure_uvmem_pfn(gpa >> PAGE_SHIFT, uvmem_pfn, kvm); 712ca9f4942SBharata B Rao 713ca9f4942SBharata B Rao pvt->gpa = gpa; 714ca9f4942SBharata B Rao pvt->kvm = kvm; 715ca9f4942SBharata B Rao 716ca9f4942SBharata B Rao dpage = pfn_to_page(uvmem_pfn); 717ca9f4942SBharata B Rao dpage->zone_device_data = pvt; 718ca9f4942SBharata B Rao lock_page(dpage); 719ca9f4942SBharata B Rao return dpage; 720ca9f4942SBharata B Rao out_clear: 721ca9f4942SBharata B Rao spin_lock(&kvmppc_uvmem_bitmap_lock); 722ca9f4942SBharata B Rao bitmap_clear(kvmppc_uvmem_bitmap, bit, 1); 723ca9f4942SBharata B Rao out: 724ca9f4942SBharata B Rao spin_unlock(&kvmppc_uvmem_bitmap_lock); 725ca9f4942SBharata B Rao return NULL; 726ca9f4942SBharata B Rao } 727ca9f4942SBharata B Rao 728ca9f4942SBharata B Rao /* 729dfaa973aSRam Pai * Alloc a PFN from private device memory pool. If @pagein is true, 730dfaa973aSRam Pai * copy page from normal memory to secure memory using UV_PAGE_IN uvcall. 731ca9f4942SBharata B Rao */ 732dfaa973aSRam Pai static int kvmppc_svm_page_in(struct vm_area_struct *vma, 733dfaa973aSRam Pai unsigned long start, 734ca9f4942SBharata B Rao unsigned long end, unsigned long gpa, struct kvm *kvm, 735dfaa973aSRam Pai unsigned long page_shift, 736dfaa973aSRam Pai bool pagein) 737ca9f4942SBharata B Rao { 738ca9f4942SBharata B Rao unsigned long src_pfn, dst_pfn = 0; 739ca9f4942SBharata B Rao struct migrate_vma mig; 740ca9f4942SBharata B Rao struct page *spage; 741ca9f4942SBharata B Rao unsigned long pfn; 742ca9f4942SBharata B Rao struct page *dpage; 743ca9f4942SBharata B Rao int ret = 0; 744ca9f4942SBharata B Rao 745ca9f4942SBharata B Rao memset(&mig, 0, sizeof(mig)); 746ca9f4942SBharata B Rao mig.vma = vma; 747ca9f4942SBharata B Rao mig.start = start; 748ca9f4942SBharata B Rao mig.end = end; 749ca9f4942SBharata B Rao mig.src = &src_pfn; 750ca9f4942SBharata B Rao mig.dst = &dst_pfn; 7515143192cSRalph Campbell mig.flags = MIGRATE_VMA_SELECT_SYSTEM; 752ca9f4942SBharata B Rao 753ca9f4942SBharata B Rao ret = migrate_vma_setup(&mig); 754ca9f4942SBharata B Rao if (ret) 755ca9f4942SBharata B Rao return ret; 756ca9f4942SBharata B Rao 757ca9f4942SBharata B Rao if (!(*mig.src & MIGRATE_PFN_MIGRATE)) { 758ca9f4942SBharata B Rao ret = -1; 759ca9f4942SBharata B Rao goto out_finalize; 760ca9f4942SBharata B Rao } 761ca9f4942SBharata B Rao 762ca9f4942SBharata B Rao dpage = kvmppc_uvmem_get_page(gpa, kvm); 763ca9f4942SBharata B Rao if (!dpage) { 764ca9f4942SBharata B Rao ret = -1; 765ca9f4942SBharata B Rao goto out_finalize; 766ca9f4942SBharata B Rao } 767ca9f4942SBharata B Rao 768dfaa973aSRam Pai if (pagein) { 769ca9f4942SBharata B Rao pfn = *mig.src >> MIGRATE_PFN_SHIFT; 770ca9f4942SBharata B Rao spage = migrate_pfn_to_page(*mig.src); 771dfaa973aSRam Pai if (spage) { 772dfaa973aSRam Pai ret = uv_page_in(kvm->arch.lpid, pfn << page_shift, 773dfaa973aSRam Pai gpa, 0, page_shift); 774dfaa973aSRam Pai if (ret) 775dfaa973aSRam Pai goto out_finalize; 776dfaa973aSRam Pai } 777dfaa973aSRam Pai } 778ca9f4942SBharata B Rao 779ab09243aSAlistair Popple *mig.dst = migrate_pfn(page_to_pfn(dpage)); 780ca9f4942SBharata B Rao migrate_vma_pages(&mig); 781ca9f4942SBharata B Rao out_finalize: 782ca9f4942SBharata B Rao migrate_vma_finalize(&mig); 783ca9f4942SBharata B Rao return ret; 784ca9f4942SBharata B Rao } 785ca9f4942SBharata B Rao 786dfaa973aSRam Pai static int kvmppc_uv_migrate_mem_slot(struct kvm *kvm, 787dfaa973aSRam Pai const struct kvm_memory_slot *memslot) 788dfaa973aSRam Pai { 789dfaa973aSRam Pai unsigned long gfn = memslot->base_gfn; 790dfaa973aSRam Pai struct vm_area_struct *vma; 791dfaa973aSRam Pai unsigned long start, end; 792dfaa973aSRam Pai int ret = 0; 793dfaa973aSRam Pai 794dfaa973aSRam Pai mmap_read_lock(kvm->mm); 795dfaa973aSRam Pai mutex_lock(&kvm->arch.uvmem_lock); 796dfaa973aSRam Pai while (kvmppc_next_nontransitioned_gfn(memslot, kvm, &gfn)) { 797dfaa973aSRam Pai ret = H_STATE; 798dfaa973aSRam Pai start = gfn_to_hva(kvm, gfn); 799dfaa973aSRam Pai if (kvm_is_error_hva(start)) 800dfaa973aSRam Pai break; 801dfaa973aSRam Pai 802dfaa973aSRam Pai end = start + (1UL << PAGE_SHIFT); 803dfaa973aSRam Pai vma = find_vma_intersection(kvm->mm, start, end); 804dfaa973aSRam Pai if (!vma || vma->vm_start > start || vma->vm_end < end) 805dfaa973aSRam Pai break; 806dfaa973aSRam Pai 807dfaa973aSRam Pai ret = kvmppc_svm_page_in(vma, start, end, 808dfaa973aSRam Pai (gfn << PAGE_SHIFT), kvm, PAGE_SHIFT, false); 809dfaa973aSRam Pai if (ret) { 810dfaa973aSRam Pai ret = H_STATE; 811dfaa973aSRam Pai break; 812dfaa973aSRam Pai } 813dfaa973aSRam Pai 814dfaa973aSRam Pai /* relinquish the cpu if needed */ 815dfaa973aSRam Pai cond_resched(); 816dfaa973aSRam Pai } 817dfaa973aSRam Pai mutex_unlock(&kvm->arch.uvmem_lock); 818dfaa973aSRam Pai mmap_read_unlock(kvm->mm); 819dfaa973aSRam Pai return ret; 820dfaa973aSRam Pai } 821dfaa973aSRam Pai 822dfaa973aSRam Pai unsigned long kvmppc_h_svm_init_done(struct kvm *kvm) 823dfaa973aSRam Pai { 824dfaa973aSRam Pai struct kvm_memslots *slots; 825dfaa973aSRam Pai struct kvm_memory_slot *memslot; 826a54d8066SMaciej S. Szmigiero int srcu_idx, bkt; 827dfaa973aSRam Pai long ret = H_SUCCESS; 828dfaa973aSRam Pai 829dfaa973aSRam Pai if (!(kvm->arch.secure_guest & KVMPPC_SECURE_INIT_START)) 830dfaa973aSRam Pai return H_UNSUPPORTED; 831dfaa973aSRam Pai 832dfaa973aSRam Pai /* migrate any unmoved normal pfn to device pfns*/ 833dfaa973aSRam Pai srcu_idx = srcu_read_lock(&kvm->srcu); 834dfaa973aSRam Pai slots = kvm_memslots(kvm); 835a54d8066SMaciej S. Szmigiero kvm_for_each_memslot(memslot, bkt, slots) { 836dfaa973aSRam Pai ret = kvmppc_uv_migrate_mem_slot(kvm, memslot); 837dfaa973aSRam Pai if (ret) { 838dfaa973aSRam Pai /* 839dfaa973aSRam Pai * The pages will remain transitioned. 840dfaa973aSRam Pai * Its the callers responsibility to 841dfaa973aSRam Pai * terminate the VM, which will undo 842dfaa973aSRam Pai * all state of the VM. Till then 843dfaa973aSRam Pai * this VM is in a erroneous state. 844dfaa973aSRam Pai * Its KVMPPC_SECURE_INIT_DONE will 845dfaa973aSRam Pai * remain unset. 846dfaa973aSRam Pai */ 847dfaa973aSRam Pai ret = H_STATE; 848dfaa973aSRam Pai goto out; 849dfaa973aSRam Pai } 850dfaa973aSRam Pai } 851dfaa973aSRam Pai 852dfaa973aSRam Pai kvm->arch.secure_guest |= KVMPPC_SECURE_INIT_DONE; 853dfaa973aSRam Pai pr_info("LPID %d went secure\n", kvm->arch.lpid); 854dfaa973aSRam Pai 855dfaa973aSRam Pai out: 856dfaa973aSRam Pai srcu_read_unlock(&kvm->srcu, srcu_idx); 857dfaa973aSRam Pai return ret; 858dfaa973aSRam Pai } 859dfaa973aSRam Pai 860ca9f4942SBharata B Rao /* 86160f0a643SBharata B Rao * Shares the page with HV, thus making it a normal page. 86260f0a643SBharata B Rao * 86360f0a643SBharata B Rao * - If the page is already secure, then provision a new page and share 86460f0a643SBharata B Rao * - If the page is a normal page, share the existing page 86560f0a643SBharata B Rao * 86660f0a643SBharata B Rao * In the former case, uses dev_pagemap_ops.migrate_to_ram handler 86760f0a643SBharata B Rao * to unmap the device page from QEMU's page tables. 86860f0a643SBharata B Rao */ 86948908a38SRam Pai static unsigned long kvmppc_share_page(struct kvm *kvm, unsigned long gpa, 87048908a38SRam Pai unsigned long page_shift) 87160f0a643SBharata B Rao { 87260f0a643SBharata B Rao 87360f0a643SBharata B Rao int ret = H_PARAMETER; 87460f0a643SBharata B Rao struct page *uvmem_page; 87560f0a643SBharata B Rao struct kvmppc_uvmem_page_pvt *pvt; 87660f0a643SBharata B Rao unsigned long pfn; 87760f0a643SBharata B Rao unsigned long gfn = gpa >> page_shift; 87860f0a643SBharata B Rao int srcu_idx; 87960f0a643SBharata B Rao unsigned long uvmem_pfn; 88060f0a643SBharata B Rao 88160f0a643SBharata B Rao srcu_idx = srcu_read_lock(&kvm->srcu); 88260f0a643SBharata B Rao mutex_lock(&kvm->arch.uvmem_lock); 88360f0a643SBharata B Rao if (kvmppc_gfn_is_uvmem_pfn(gfn, kvm, &uvmem_pfn)) { 88460f0a643SBharata B Rao uvmem_page = pfn_to_page(uvmem_pfn); 88560f0a643SBharata B Rao pvt = uvmem_page->zone_device_data; 88660f0a643SBharata B Rao pvt->skip_page_out = true; 887651a6310SRam Pai /* 888651a6310SRam Pai * do not drop the GFN. It is a valid GFN 889651a6310SRam Pai * that is transitioned to a shared GFN. 890651a6310SRam Pai */ 891651a6310SRam Pai pvt->remove_gfn = false; 89260f0a643SBharata B Rao } 89360f0a643SBharata B Rao 89460f0a643SBharata B Rao retry: 89560f0a643SBharata B Rao mutex_unlock(&kvm->arch.uvmem_lock); 89660f0a643SBharata B Rao pfn = gfn_to_pfn(kvm, gfn); 89760f0a643SBharata B Rao if (is_error_noslot_pfn(pfn)) 89860f0a643SBharata B Rao goto out; 89960f0a643SBharata B Rao 90060f0a643SBharata B Rao mutex_lock(&kvm->arch.uvmem_lock); 90160f0a643SBharata B Rao if (kvmppc_gfn_is_uvmem_pfn(gfn, kvm, &uvmem_pfn)) { 90260f0a643SBharata B Rao uvmem_page = pfn_to_page(uvmem_pfn); 90360f0a643SBharata B Rao pvt = uvmem_page->zone_device_data; 90460f0a643SBharata B Rao pvt->skip_page_out = true; 905651a6310SRam Pai pvt->remove_gfn = false; /* it continues to be a valid GFN */ 90660f0a643SBharata B Rao kvm_release_pfn_clean(pfn); 90760f0a643SBharata B Rao goto retry; 90860f0a643SBharata B Rao } 90960f0a643SBharata B Rao 910651a6310SRam Pai if (!uv_page_in(kvm->arch.lpid, pfn << page_shift, gpa, 0, 911651a6310SRam Pai page_shift)) { 912651a6310SRam Pai kvmppc_gfn_shared(gfn, kvm); 91360f0a643SBharata B Rao ret = H_SUCCESS; 914651a6310SRam Pai } 91560f0a643SBharata B Rao kvm_release_pfn_clean(pfn); 91660f0a643SBharata B Rao mutex_unlock(&kvm->arch.uvmem_lock); 91760f0a643SBharata B Rao out: 91860f0a643SBharata B Rao srcu_read_unlock(&kvm->srcu, srcu_idx); 91960f0a643SBharata B Rao return ret; 92060f0a643SBharata B Rao } 92160f0a643SBharata B Rao 92260f0a643SBharata B Rao /* 923ca9f4942SBharata B Rao * H_SVM_PAGE_IN: Move page from normal memory to secure memory. 92460f0a643SBharata B Rao * 92560f0a643SBharata B Rao * H_PAGE_IN_SHARED flag makes the page shared which means that the same 92660f0a643SBharata B Rao * memory in is visible from both UV and HV. 927ca9f4942SBharata B Rao */ 92848908a38SRam Pai unsigned long kvmppc_h_svm_page_in(struct kvm *kvm, unsigned long gpa, 92948908a38SRam Pai unsigned long flags, 93048908a38SRam Pai unsigned long page_shift) 931ca9f4942SBharata B Rao { 932ca9f4942SBharata B Rao unsigned long start, end; 933ca9f4942SBharata B Rao struct vm_area_struct *vma; 934ca9f4942SBharata B Rao int srcu_idx; 935ca9f4942SBharata B Rao unsigned long gfn = gpa >> page_shift; 936ca9f4942SBharata B Rao int ret; 937ca9f4942SBharata B Rao 938ca9f4942SBharata B Rao if (!(kvm->arch.secure_guest & KVMPPC_SECURE_INIT_START)) 939ca9f4942SBharata B Rao return H_UNSUPPORTED; 940ca9f4942SBharata B Rao 941ca9f4942SBharata B Rao if (page_shift != PAGE_SHIFT) 942ca9f4942SBharata B Rao return H_P3; 943ca9f4942SBharata B Rao 94460f0a643SBharata B Rao if (flags & ~H_PAGE_IN_SHARED) 945ca9f4942SBharata B Rao return H_P2; 946ca9f4942SBharata B Rao 94760f0a643SBharata B Rao if (flags & H_PAGE_IN_SHARED) 94860f0a643SBharata B Rao return kvmppc_share_page(kvm, gpa, page_shift); 94960f0a643SBharata B Rao 950ca9f4942SBharata B Rao ret = H_PARAMETER; 951ca9f4942SBharata B Rao srcu_idx = srcu_read_lock(&kvm->srcu); 9522027a24aSRam Pai mmap_read_lock(kvm->mm); 953ca9f4942SBharata B Rao 954ca9f4942SBharata B Rao start = gfn_to_hva(kvm, gfn); 955ca9f4942SBharata B Rao if (kvm_is_error_hva(start)) 956ca9f4942SBharata B Rao goto out; 957ca9f4942SBharata B Rao 958ca9f4942SBharata B Rao mutex_lock(&kvm->arch.uvmem_lock); 959ca9f4942SBharata B Rao /* Fail the page-in request of an already paged-in page */ 960ca9f4942SBharata B Rao if (kvmppc_gfn_is_uvmem_pfn(gfn, kvm, NULL)) 961ca9f4942SBharata B Rao goto out_unlock; 962ca9f4942SBharata B Rao 963ca9f4942SBharata B Rao end = start + (1UL << page_shift); 964ca9f4942SBharata B Rao vma = find_vma_intersection(kvm->mm, start, end); 965ca9f4942SBharata B Rao if (!vma || vma->vm_start > start || vma->vm_end < end) 966ca9f4942SBharata B Rao goto out_unlock; 967ca9f4942SBharata B Rao 968dfaa973aSRam Pai if (kvmppc_svm_page_in(vma, start, end, gpa, kvm, page_shift, 969dfaa973aSRam Pai true)) 970dfaa973aSRam Pai goto out_unlock; 971dfaa973aSRam Pai 972ca9f4942SBharata B Rao ret = H_SUCCESS; 973651a6310SRam Pai 974ca9f4942SBharata B Rao out_unlock: 975ca9f4942SBharata B Rao mutex_unlock(&kvm->arch.uvmem_lock); 976ca9f4942SBharata B Rao out: 977d8ed45c5SMichel Lespinasse mmap_read_unlock(kvm->mm); 978ca9f4942SBharata B Rao srcu_read_unlock(&kvm->srcu, srcu_idx); 979ca9f4942SBharata B Rao return ret; 980ca9f4942SBharata B Rao } 981ca9f4942SBharata B Rao 982ca9f4942SBharata B Rao 983ca9f4942SBharata B Rao /* 984ca9f4942SBharata B Rao * Fault handler callback that gets called when HV touches any page that 985ca9f4942SBharata B Rao * has been moved to secure memory, we ask UV to give back the page by 986ca9f4942SBharata B Rao * issuing UV_PAGE_OUT uvcall. 987ca9f4942SBharata B Rao * 988ca9f4942SBharata B Rao * This eventually results in dropping of device PFN and the newly 989ca9f4942SBharata B Rao * provisioned page/PFN gets populated in QEMU page tables. 990ca9f4942SBharata B Rao */ 991ca9f4942SBharata B Rao static vm_fault_t kvmppc_uvmem_migrate_to_ram(struct vm_fault *vmf) 992ca9f4942SBharata B Rao { 993ca9f4942SBharata B Rao struct kvmppc_uvmem_page_pvt *pvt = vmf->page->zone_device_data; 994ca9f4942SBharata B Rao 995ca9f4942SBharata B Rao if (kvmppc_svm_page_out(vmf->vma, vmf->address, 996ca9f4942SBharata B Rao vmf->address + PAGE_SIZE, PAGE_SHIFT, 997ca9f4942SBharata B Rao pvt->kvm, pvt->gpa)) 998ca9f4942SBharata B Rao return VM_FAULT_SIGBUS; 999ca9f4942SBharata B Rao else 1000ca9f4942SBharata B Rao return 0; 1001ca9f4942SBharata B Rao } 1002ca9f4942SBharata B Rao 1003ca9f4942SBharata B Rao /* 1004ca9f4942SBharata B Rao * Release the device PFN back to the pool 1005ca9f4942SBharata B Rao * 1006651a6310SRam Pai * Gets called when secure GFN tranistions from a secure-PFN 1007651a6310SRam Pai * to a normal PFN during H_SVM_PAGE_OUT. 1008ca9f4942SBharata B Rao * Gets called with kvm->arch.uvmem_lock held. 1009ca9f4942SBharata B Rao */ 1010ca9f4942SBharata B Rao static void kvmppc_uvmem_page_free(struct page *page) 1011ca9f4942SBharata B Rao { 1012ca9f4942SBharata B Rao unsigned long pfn = page_to_pfn(page) - 1013a4574f63SDan Williams (kvmppc_uvmem_pgmap.range.start >> PAGE_SHIFT); 1014ca9f4942SBharata B Rao struct kvmppc_uvmem_page_pvt *pvt; 1015ca9f4942SBharata B Rao 1016ca9f4942SBharata B Rao spin_lock(&kvmppc_uvmem_bitmap_lock); 1017ca9f4942SBharata B Rao bitmap_clear(kvmppc_uvmem_bitmap, pfn, 1); 1018ca9f4942SBharata B Rao spin_unlock(&kvmppc_uvmem_bitmap_lock); 1019ca9f4942SBharata B Rao 1020ca9f4942SBharata B Rao pvt = page->zone_device_data; 1021ca9f4942SBharata B Rao page->zone_device_data = NULL; 1022651a6310SRam Pai if (pvt->remove_gfn) 1023651a6310SRam Pai kvmppc_gfn_remove(pvt->gpa >> PAGE_SHIFT, pvt->kvm); 1024651a6310SRam Pai else 1025651a6310SRam Pai kvmppc_gfn_secure_mem_pfn(pvt->gpa >> PAGE_SHIFT, pvt->kvm); 1026ca9f4942SBharata B Rao kfree(pvt); 1027ca9f4942SBharata B Rao } 1028ca9f4942SBharata B Rao 1029ca9f4942SBharata B Rao static const struct dev_pagemap_ops kvmppc_uvmem_ops = { 1030ca9f4942SBharata B Rao .page_free = kvmppc_uvmem_page_free, 1031ca9f4942SBharata B Rao .migrate_to_ram = kvmppc_uvmem_migrate_to_ram, 1032ca9f4942SBharata B Rao }; 1033ca9f4942SBharata B Rao 1034ca9f4942SBharata B Rao /* 1035ca9f4942SBharata B Rao * H_SVM_PAGE_OUT: Move page from secure memory to normal memory. 1036ca9f4942SBharata B Rao */ 1037ca9f4942SBharata B Rao unsigned long 1038ca9f4942SBharata B Rao kvmppc_h_svm_page_out(struct kvm *kvm, unsigned long gpa, 1039ca9f4942SBharata B Rao unsigned long flags, unsigned long page_shift) 1040ca9f4942SBharata B Rao { 1041ca9f4942SBharata B Rao unsigned long gfn = gpa >> page_shift; 1042ca9f4942SBharata B Rao unsigned long start, end; 1043ca9f4942SBharata B Rao struct vm_area_struct *vma; 1044ca9f4942SBharata B Rao int srcu_idx; 1045ca9f4942SBharata B Rao int ret; 1046ca9f4942SBharata B Rao 1047ca9f4942SBharata B Rao if (!(kvm->arch.secure_guest & KVMPPC_SECURE_INIT_START)) 1048ca9f4942SBharata B Rao return H_UNSUPPORTED; 1049ca9f4942SBharata B Rao 1050ca9f4942SBharata B Rao if (page_shift != PAGE_SHIFT) 1051ca9f4942SBharata B Rao return H_P3; 1052ca9f4942SBharata B Rao 1053ca9f4942SBharata B Rao if (flags) 1054ca9f4942SBharata B Rao return H_P2; 1055ca9f4942SBharata B Rao 1056ca9f4942SBharata B Rao ret = H_PARAMETER; 1057ca9f4942SBharata B Rao srcu_idx = srcu_read_lock(&kvm->srcu); 1058d8ed45c5SMichel Lespinasse mmap_read_lock(kvm->mm); 1059ca9f4942SBharata B Rao start = gfn_to_hva(kvm, gfn); 1060ca9f4942SBharata B Rao if (kvm_is_error_hva(start)) 1061ca9f4942SBharata B Rao goto out; 1062ca9f4942SBharata B Rao 1063ca9f4942SBharata B Rao end = start + (1UL << page_shift); 1064ca9f4942SBharata B Rao vma = find_vma_intersection(kvm->mm, start, end); 1065ca9f4942SBharata B Rao if (!vma || vma->vm_start > start || vma->vm_end < end) 1066ca9f4942SBharata B Rao goto out; 1067ca9f4942SBharata B Rao 1068ca9f4942SBharata B Rao if (!kvmppc_svm_page_out(vma, start, end, page_shift, kvm, gpa)) 1069ca9f4942SBharata B Rao ret = H_SUCCESS; 1070ca9f4942SBharata B Rao out: 1071d8ed45c5SMichel Lespinasse mmap_read_unlock(kvm->mm); 1072ca9f4942SBharata B Rao srcu_read_unlock(&kvm->srcu, srcu_idx); 1073ca9f4942SBharata B Rao return ret; 1074ca9f4942SBharata B Rao } 1075ca9f4942SBharata B Rao 1076008e359cSBharata B Rao int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn) 1077008e359cSBharata B Rao { 1078008e359cSBharata B Rao unsigned long pfn; 1079008e359cSBharata B Rao int ret = U_SUCCESS; 1080008e359cSBharata B Rao 1081008e359cSBharata B Rao pfn = gfn_to_pfn(kvm, gfn); 1082008e359cSBharata B Rao if (is_error_noslot_pfn(pfn)) 1083008e359cSBharata B Rao return -EFAULT; 1084008e359cSBharata B Rao 1085008e359cSBharata B Rao mutex_lock(&kvm->arch.uvmem_lock); 1086008e359cSBharata B Rao if (kvmppc_gfn_is_uvmem_pfn(gfn, kvm, NULL)) 1087008e359cSBharata B Rao goto out; 1088008e359cSBharata B Rao 1089008e359cSBharata B Rao ret = uv_page_in(kvm->arch.lpid, pfn << PAGE_SHIFT, gfn << PAGE_SHIFT, 1090008e359cSBharata B Rao 0, PAGE_SHIFT); 1091008e359cSBharata B Rao out: 1092008e359cSBharata B Rao kvm_release_pfn_clean(pfn); 1093008e359cSBharata B Rao mutex_unlock(&kvm->arch.uvmem_lock); 1094008e359cSBharata B Rao return (ret == U_SUCCESS) ? RESUME_GUEST : -EFAULT; 1095008e359cSBharata B Rao } 1096008e359cSBharata B Rao 1097a2ce7200SLaurent Dufour int kvmppc_uvmem_memslot_create(struct kvm *kvm, const struct kvm_memory_slot *new) 1098a2ce7200SLaurent Dufour { 1099a2ce7200SLaurent Dufour int ret = __kvmppc_uvmem_memslot_create(kvm, new); 1100a2ce7200SLaurent Dufour 1101a2ce7200SLaurent Dufour if (!ret) 1102a2ce7200SLaurent Dufour ret = kvmppc_uv_migrate_mem_slot(kvm, new); 1103a2ce7200SLaurent Dufour 1104a2ce7200SLaurent Dufour return ret; 1105a2ce7200SLaurent Dufour } 1106a2ce7200SLaurent Dufour 1107a2ce7200SLaurent Dufour void kvmppc_uvmem_memslot_delete(struct kvm *kvm, const struct kvm_memory_slot *old) 1108a2ce7200SLaurent Dufour { 1109a2ce7200SLaurent Dufour __kvmppc_uvmem_memslot_delete(kvm, old); 1110a2ce7200SLaurent Dufour } 1111a2ce7200SLaurent Dufour 1112ca9f4942SBharata B Rao static u64 kvmppc_get_secmem_size(void) 1113ca9f4942SBharata B Rao { 1114ca9f4942SBharata B Rao struct device_node *np; 1115ca9f4942SBharata B Rao int i, len; 1116ca9f4942SBharata B Rao const __be32 *prop; 1117ca9f4942SBharata B Rao u64 size = 0; 1118ca9f4942SBharata B Rao 1119512721d2SLaurent Dufour /* 1120512721d2SLaurent Dufour * First try the new ibm,secure-memory nodes which supersede the 1121512721d2SLaurent Dufour * secure-memory-ranges property. 1122512721d2SLaurent Dufour * If we found some, no need to read the deprecated ones. 1123512721d2SLaurent Dufour */ 1124512721d2SLaurent Dufour for_each_compatible_node(np, NULL, "ibm,secure-memory") { 1125512721d2SLaurent Dufour prop = of_get_property(np, "reg", &len); 1126512721d2SLaurent Dufour if (!prop) 1127512721d2SLaurent Dufour continue; 1128512721d2SLaurent Dufour size += of_read_number(prop + 2, 2); 1129512721d2SLaurent Dufour } 1130512721d2SLaurent Dufour if (size) 1131512721d2SLaurent Dufour return size; 1132512721d2SLaurent Dufour 1133ca9f4942SBharata B Rao np = of_find_compatible_node(NULL, NULL, "ibm,uv-firmware"); 1134ca9f4942SBharata B Rao if (!np) 1135ca9f4942SBharata B Rao goto out; 1136ca9f4942SBharata B Rao 1137ca9f4942SBharata B Rao prop = of_get_property(np, "secure-memory-ranges", &len); 1138ca9f4942SBharata B Rao if (!prop) 1139ca9f4942SBharata B Rao goto out_put; 1140ca9f4942SBharata B Rao 1141ca9f4942SBharata B Rao for (i = 0; i < len / (sizeof(*prop) * 4); i++) 1142ca9f4942SBharata B Rao size += of_read_number(prop + (i * 4) + 2, 2); 1143ca9f4942SBharata B Rao 1144ca9f4942SBharata B Rao out_put: 1145ca9f4942SBharata B Rao of_node_put(np); 1146ca9f4942SBharata B Rao out: 1147ca9f4942SBharata B Rao return size; 1148ca9f4942SBharata B Rao } 1149ca9f4942SBharata B Rao 1150ca9f4942SBharata B Rao int kvmppc_uvmem_init(void) 1151ca9f4942SBharata B Rao { 1152ca9f4942SBharata B Rao int ret = 0; 1153ca9f4942SBharata B Rao unsigned long size; 1154ca9f4942SBharata B Rao struct resource *res; 1155ca9f4942SBharata B Rao void *addr; 1156ca9f4942SBharata B Rao unsigned long pfn_last, pfn_first; 1157ca9f4942SBharata B Rao 1158ca9f4942SBharata B Rao size = kvmppc_get_secmem_size(); 1159ca9f4942SBharata B Rao if (!size) { 1160ca9f4942SBharata B Rao /* 1161ca9f4942SBharata B Rao * Don't fail the initialization of kvm-hv module if 1162ca9f4942SBharata B Rao * the platform doesn't export ibm,uv-firmware node. 1163ca9f4942SBharata B Rao * Let normal guests run on such PEF-disabled platform. 1164ca9f4942SBharata B Rao */ 1165ca9f4942SBharata B Rao pr_info("KVMPPC-UVMEM: No support for secure guests\n"); 1166ca9f4942SBharata B Rao goto out; 1167ca9f4942SBharata B Rao } 1168ca9f4942SBharata B Rao 1169ca9f4942SBharata B Rao res = request_free_mem_region(&iomem_resource, size, "kvmppc_uvmem"); 1170ca9f4942SBharata B Rao if (IS_ERR(res)) { 1171ca9f4942SBharata B Rao ret = PTR_ERR(res); 1172ca9f4942SBharata B Rao goto out; 1173ca9f4942SBharata B Rao } 1174ca9f4942SBharata B Rao 1175ca9f4942SBharata B Rao kvmppc_uvmem_pgmap.type = MEMORY_DEVICE_PRIVATE; 1176a4574f63SDan Williams kvmppc_uvmem_pgmap.range.start = res->start; 1177a4574f63SDan Williams kvmppc_uvmem_pgmap.range.end = res->end; 1178b7b3c01bSDan Williams kvmppc_uvmem_pgmap.nr_range = 1; 1179ca9f4942SBharata B Rao kvmppc_uvmem_pgmap.ops = &kvmppc_uvmem_ops; 1180f894ddd5SChristoph Hellwig /* just one global instance: */ 1181f894ddd5SChristoph Hellwig kvmppc_uvmem_pgmap.owner = &kvmppc_uvmem_pgmap; 1182ca9f4942SBharata B Rao addr = memremap_pages(&kvmppc_uvmem_pgmap, NUMA_NO_NODE); 1183ca9f4942SBharata B Rao if (IS_ERR(addr)) { 1184ca9f4942SBharata B Rao ret = PTR_ERR(addr); 1185ca9f4942SBharata B Rao goto out_free_region; 1186ca9f4942SBharata B Rao } 1187ca9f4942SBharata B Rao 1188ca9f4942SBharata B Rao pfn_first = res->start >> PAGE_SHIFT; 1189ca9f4942SBharata B Rao pfn_last = pfn_first + (resource_size(res) >> PAGE_SHIFT); 1190ca9f4942SBharata B Rao kvmppc_uvmem_bitmap = kcalloc(BITS_TO_LONGS(pfn_last - pfn_first), 1191ca9f4942SBharata B Rao sizeof(unsigned long), GFP_KERNEL); 1192ca9f4942SBharata B Rao if (!kvmppc_uvmem_bitmap) { 1193ca9f4942SBharata B Rao ret = -ENOMEM; 1194ca9f4942SBharata B Rao goto out_unmap; 1195ca9f4942SBharata B Rao } 1196ca9f4942SBharata B Rao 1197ca9f4942SBharata B Rao pr_info("KVMPPC-UVMEM: Secure Memory size 0x%lx\n", size); 1198ca9f4942SBharata B Rao return ret; 1199ca9f4942SBharata B Rao out_unmap: 1200ca9f4942SBharata B Rao memunmap_pages(&kvmppc_uvmem_pgmap); 1201ca9f4942SBharata B Rao out_free_region: 1202ca9f4942SBharata B Rao release_mem_region(res->start, size); 1203ca9f4942SBharata B Rao out: 1204ca9f4942SBharata B Rao return ret; 1205ca9f4942SBharata B Rao } 1206ca9f4942SBharata B Rao 1207ca9f4942SBharata B Rao void kvmppc_uvmem_free(void) 1208ca9f4942SBharata B Rao { 12099bee484bSFabiano Rosas if (!kvmppc_uvmem_bitmap) 12109bee484bSFabiano Rosas return; 12119bee484bSFabiano Rosas 1212ca9f4942SBharata B Rao memunmap_pages(&kvmppc_uvmem_pgmap); 1213a4574f63SDan Williams release_mem_region(kvmppc_uvmem_pgmap.range.start, 1214a4574f63SDan Williams range_len(&kvmppc_uvmem_pgmap.range)); 1215ca9f4942SBharata B Rao kfree(kvmppc_uvmem_bitmap); 1216ca9f4942SBharata B Rao } 1217