diff options
| -rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 4 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 2 | ||||
| -rw-r--r-- | arch/powerpc/kvm/Makefile | 2 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s_64_vio.c | 150 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s_64_vio_hv.c | 3 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s_hv.c | 109 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s_pr.c | 7 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s_pr_papr.c | 18 | ||||
| -rw-r--r-- | arch/powerpc/kvm/powerpc.c | 8 |
9 files changed, 191 insertions, 112 deletions
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 42a527e70490..d848cdc49715 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
| @@ -237,7 +237,6 @@ struct kvm_arch { | |||
| 237 | unsigned long vrma_slb_v; | 237 | unsigned long vrma_slb_v; |
| 238 | int rma_setup_done; | 238 | int rma_setup_done; |
| 239 | int using_mmu_notifiers; | 239 | int using_mmu_notifiers; |
| 240 | struct list_head spapr_tce_tables; | ||
| 241 | spinlock_t slot_phys_lock; | 240 | spinlock_t slot_phys_lock; |
| 242 | unsigned long *slot_phys[KVM_MEM_SLOTS_NUM]; | 241 | unsigned long *slot_phys[KVM_MEM_SLOTS_NUM]; |
| 243 | int slot_npages[KVM_MEM_SLOTS_NUM]; | 242 | int slot_npages[KVM_MEM_SLOTS_NUM]; |
| @@ -245,6 +244,9 @@ struct kvm_arch { | |||
| 245 | struct kvmppc_vcore *vcores[KVM_MAX_VCORES]; | 244 | struct kvmppc_vcore *vcores[KVM_MAX_VCORES]; |
| 246 | struct kvmppc_linear_info *hpt_li; | 245 | struct kvmppc_linear_info *hpt_li; |
| 247 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | 246 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ |
| 247 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
| 248 | struct list_head spapr_tce_tables; | ||
| 249 | #endif | ||
| 248 | }; | 250 | }; |
| 249 | 251 | ||
| 250 | /* | 252 | /* |
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 7f0a3dae7cde..c1069f63dcaf 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
| @@ -126,6 +126,8 @@ extern void kvmppc_map_vrma(struct kvm_vcpu *vcpu, | |||
| 126 | extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu); | 126 | extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu); |
| 127 | extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, | 127 | extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, |
| 128 | struct kvm_create_spapr_tce *args); | 128 | struct kvm_create_spapr_tce *args); |
| 129 | extern long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, | ||
| 130 | unsigned long ioba, unsigned long tce); | ||
| 129 | extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, | 131 | extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, |
| 130 | struct kvm_allocate_rma *rma); | 132 | struct kvm_allocate_rma *rma); |
| 131 | extern struct kvmppc_linear_info *kvm_alloc_rma(void); | 133 | extern struct kvmppc_linear_info *kvm_alloc_rma(void); |
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 25225aea4c39..c2a08636e6d4 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile | |||
| @@ -54,6 +54,7 @@ kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \ | |||
| 54 | book3s_paired_singles.o \ | 54 | book3s_paired_singles.o \ |
| 55 | book3s_pr.o \ | 55 | book3s_pr.o \ |
| 56 | book3s_pr_papr.o \ | 56 | book3s_pr_papr.o \ |
| 57 | book3s_64_vio_hv.o \ | ||
| 57 | book3s_emulate.o \ | 58 | book3s_emulate.o \ |
| 58 | book3s_interrupts.o \ | 59 | book3s_interrupts.o \ |
| 59 | book3s_mmu_hpte.o \ | 60 | book3s_mmu_hpte.o \ |
| @@ -78,6 +79,7 @@ kvm-book3s_64-module-objs := \ | |||
| 78 | powerpc.o \ | 79 | powerpc.o \ |
| 79 | emulate.o \ | 80 | emulate.o \ |
| 80 | book3s.o \ | 81 | book3s.o \ |
| 82 | book3s_64_vio.o \ | ||
| 81 | $(kvm-book3s_64-objs-y) | 83 | $(kvm-book3s_64-objs-y) |
| 82 | 84 | ||
| 83 | kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-module-objs) | 85 | kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-module-objs) |
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c new file mode 100644 index 000000000000..72ffc899c082 --- /dev/null +++ b/arch/powerpc/kvm/book3s_64_vio.c | |||
| @@ -0,0 +1,150 @@ | |||
| 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; | ||
