1 /* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License, version 2, as 4 * published by the Free Software Foundation. 5 * 6 * This program is distributed in the hope that it will be useful, 7 * but WITHOUT ANY WARRANTY; without even the implied warranty of 8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 * GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License 12 * along with this program; if not, write to the Free Software 13 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 14 * 15 * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> 16 * Copyright 2011 David Gibson, IBM Corporation <dwg@au1.ibm.com> 17 */ 18 19 #include <linux/types.h> 20 #include <linux/string.h> 21 #include <linux/kvm.h> 22 #include <linux/kvm_host.h> 23 #include <linux/highmem.h> 24 #include <linux/gfp.h> 25 #include <linux/slab.h> 26 #include <linux/hugetlb.h> 27 #include <linux/list.h> 28 #include <linux/anon_inodes.h> 29 30 #include <asm/tlbflush.h> 31 #include <asm/kvm_ppc.h> 32 #include <asm/kvm_book3s.h> 33 #include <asm/mmu-hash64.h> 34 #include <asm/hvcall.h> 35 #include <asm/synch.h> 36 #include <asm/ppc-opcode.h> 37 #include <asm/kvm_host.h> 38 #include <asm/udbg.h> 39 40 #define TCES_PER_PAGE (PAGE_SIZE / sizeof(u64)) 41 42 static long kvmppc_stt_npages(unsigned long window_size) 43 { 44 return ALIGN((window_size >> SPAPR_TCE_SHIFT) 45 * sizeof(u64), PAGE_SIZE) / PAGE_SIZE; 46 } 47 48 static void release_spapr_tce_table(struct kvmppc_spapr_tce_table *stt) 49 { 50 struct kvm *kvm = stt->kvm; 51 int i; 52 53 mutex_lock(&kvm->lock); 54 list_del(&stt->list); 55 for (i = 0; i < kvmppc_stt_npages(stt->window_size); i++) 56 __free_page(stt->pages[i]); 57 kfree(stt); 58 mutex_unlock(&kvm->lock); 59 60 kvm_put_kvm(kvm); 61 } 62 63 static int kvm_spapr_tce_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 64 { 65 struct kvmppc_spapr_tce_table *stt = vma->vm_file->private_data; 66 struct page *page; 67 68 if (vmf->pgoff >= kvmppc_stt_npages(stt->window_size)) 69 return VM_FAULT_SIGBUS; 70 71 page = stt->pages[vmf->pgoff]; 72 get_page(page); 73 vmf->page = page; 74 return 0; 75 } 76 77 static const struct vm_operations_struct kvm_spapr_tce_vm_ops = { 78 .fault = kvm_spapr_tce_fault, 79 }; 80 81 static int kvm_spapr_tce_mmap(struct file *file, struct vm_area_struct *vma) 82 { 83 vma->vm_ops = &kvm_spapr_tce_vm_ops; 84 return 0; 85 } 86 87 static int kvm_spapr_tce_release(struct inode *inode, struct file *filp) 88 { 89 struct kvmppc_spapr_tce_table *stt = filp->private_data; 90 91 release_spapr_tce_table(stt); 92 return 0; 93 } 94 95 static struct file_operations kvm_spapr_tce_fops = { 96 .mmap = kvm_spapr_tce_mmap, 97 .release = kvm_spapr_tce_release, 98 }; 99 100 long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, 101 struct kvm_create_spapr_tce *args) 102 { 103 struct kvmppc_spapr_tce_table *stt = NULL; 104 long npages; 105 int ret = -ENOMEM; 106 int i; 107 108 /* Check this LIOBN hasn't been previously allocated */ 109 list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) { 110 if (stt->liobn == args->liobn) 111 return -EBUSY; 112 } 113 114 npages = kvmppc_stt_npages(args->window_size); 115 116 stt = kzalloc(sizeof(*stt) + npages * sizeof(struct page *), 117 GFP_KERNEL); 118 if (!stt) 119 goto fail; 120 121 stt->liobn = args->liobn; 122 stt->window_size = args->window_size; 123 stt->kvm = kvm; 124 125 for (i = 0; i < npages; i++) { 126 stt->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO); 127 if (!stt->pages[i]) 128 goto fail; 129 } 130 131 kvm_get_kvm(kvm); 132 133 mutex_lock(&kvm->lock); 134 list_add(&stt->list, &kvm->arch.spapr_tce_tables); 135 136 mutex_unlock(&kvm->lock); 137 138 return anon_inode_getfd("kvm-spapr-tce", &kvm_spapr_tce_fops, 139 stt, O_RDWR); 140 141 fail: 142 if (stt) { 143 for (i = 0; i < npages; i++) 144 if (stt->pages[i]) 145 __free_page(stt->pages[i]); 146 147 kfree(stt); 148 } 149 return ret; 150 } 151