aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-03-15 17:58:34 -0400
committerAlexander Graf <agraf@suse.de>2012-05-06 10:19:11 -0400
commitf31e65e1170edba4a86bd8cba0318e251d3746d0 (patch)
tree511cd618867f7335e451d416cb7fc8e6944606ff /arch/powerpc
parent4444aa5f78eff73a353c8c4784cda2de74dea54b (diff)
kvm/book3s: Make kernel emulated H_PUT_TCE available for "PR" KVM
There is nothing in the code for emulating TCE tables in the kernel that prevents it from working on "PR" KVM... other than ifdef's and location of the code. This and moves the bulk of the code there to a new file called book3s_64_vio.c. This speeds things up a bit on my G5. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> [agraf: fix for hv kvm, 32bit, whitespace] Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm_host.h4
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h2
-rw-r--r--arch/powerpc/kvm/Makefile2
-rw-r--r--arch/powerpc/kvm/book3s_64_vio.c150
-rw-r--r--arch/powerpc/kvm/book3s_64_vio_hv.c3
-rw-r--r--arch/powerpc/kvm/book3s_hv.c109
-rw-r--r--arch/powerpc/kvm/book3s_pr.c7
-rw-r--r--arch/powerpc/kvm/book3s_pr_papr.c18
-rw-r--r--arch/powerpc/kvm/powerpc.c8
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,
126extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu); 126extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu);
127extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, 127extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
128 struct kvm_create_spapr_tce *args); 128 struct kvm_create_spapr_tce *args);
129extern long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
130 unsigned long ioba, unsigned long tce);
129extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, 131extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm,
130 struct kvm_allocate_rma *rma); 132 struct kvm_allocate_rma *rma);
131extern struct kvmppc_linear_info *kvm_alloc_rma(void); 133extern 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
83kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-module-objs) 85kvm-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
42static 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
48static 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
63static 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
77static const struct vm_operations_struct kvm_spapr_tce_vm_ops = {
78 .fault = kvm_spapr_tce_fault,
79};
80
81static 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
87static 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
95static struct file_operations kvm_spapr_tce_fops = {
96 .mmap = kvm_spapr_tce_mmap,
97 .release = kvm_spapr_tce_release,
98};
99
100long 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
141fail:
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}
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c
index ea0f8c537c28..30c2f3b134c6 100644
--- a/arch/powerpc/kvm/book3s_64_vio_hv.c
+++ b/arch/powerpc/kvm/book3s_64_vio_hv.c
@@ -38,6 +38,9 @@
38 38
39#define TCES_PER_PAGE (PAGE_SIZE / sizeof(u64)) 39#define TCES_PER_PAGE (PAGE_SIZE / sizeof(u64))
40 40
41/* WARNING: This will be called in real-mode on HV KVM and virtual
42 * mode on PR KVM
43 */
41long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, 44long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
42 unsigned long ioba, unsigned long tce) 45 unsigned long ioba, unsigned long tce)
43{ 46{
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 907935764de0..59c296743595 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1093,115 +1093,6 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
1093 return r; 1093 return r;
1094} 1094}
1095 1095
1096static long kvmppc_stt_npages(unsigned long window_size)
1097{
1098 return ALIGN((window_size >> SPAPR_TCE_SHIFT)
1099 * sizeof(u64), PAGE_SIZE) / PAGE_SIZE;
1100}
1101
1102static void release_spapr_tce_table(struct kvmppc_spapr_tce_table *stt)
1103{
1104 struct kvm *kvm = stt->kvm;
1105 int i;
1106
1107 mutex_lock(&kvm->lock);
1108 list_del(&stt->list);
1109 for (i = 0; i < kvmppc_stt_npages(stt->window_size); i++)
1110 __free_page(stt->pages[i]);
1111 kfree(stt);
1112 mutex_unlock(&kvm->lock);
1113
1114 kvm_put_kvm(kvm);
1115}
1116
1117static int kvm_spapr_tce_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1118{
1119 struct kvmppc_spapr_tce_table *stt = vma->vm_file->private_data;
1120 struct page *page;
1121
1122 if (vmf->pgoff >= kvmppc_stt_npages(stt->window_size))
1123 return VM_FAULT_SIGBUS;
1124
1125 page = stt->pages[vmf->pgoff];
1126 get_page(page);
1127 vmf->page = page;
1128 return 0;
1129}
1130
1131static const struct vm_operations_struct kvm_spapr_tce_vm_ops = {
1132 .fault = kvm_spapr_tce_fault,
1133};
1134
1135static int kvm_spapr_tce_mmap(struct file *file, struct vm_area_struct *vma)
1136{
1137 vma->vm_ops = &kvm_spapr_tce_vm_ops;
1138 return 0;
1139}
1140
1141static int kvm_spapr_tce_release(struct inode *inode, struct file *filp)
1142{
1143 struct kvmppc_spapr_tce_table *stt = filp->private_data;
1144
1145 release_spapr_tce_table(stt);
1146 return 0;
1147}
1148
1149static struct file_operations kvm_spapr_tce_fops = {
1150 .mmap = kvm_spapr_tce_mmap,
1151 .release = kvm_spapr_tce_release,
1152};
1153
1154long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
1155 struct kvm_create_spapr_tce *args)
1156{
1157 struct kvmppc_spapr_tce_table *stt = NULL;
1158 long npages;
1159 int ret = -ENOMEM;
1160 int i;
1161
1162 /* Check this LIOBN hasn't been previously allocated */
1163 list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) {
1164 if (stt->liobn == args->liobn)
1165 return -EBUSY;
1166 }
1167
1168 npages = kvmppc_stt_npages(args->window_size);
1169
1170 stt = kzalloc(sizeof(*stt) + npages* sizeof(struct page *),
1171 GFP_KERNEL);
1172 if (!stt)
1173 goto fail;
1174
1175 stt->liobn = args->liobn;
1176 stt->window_size = args->window_size;
1177 stt->kvm = kvm;
1178
1179 for (i = 0; i < npages; i++) {
1180 stt->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);
1181 if (!stt->pages[i])
1182 goto fail;
1183 }
1184
1185 kvm_get_kvm(kvm);
1186
1187 mutex_lock(&kvm->lock);
1188 list_add(&stt->list, &kvm->arch.spapr_tce_tables);
1189
1190 mutex_unlock(&kvm->lock);
1191
1192 return anon_inode_getfd("kvm-spapr-tce", &kvm_spapr_tce_fops,
1193 stt, O_RDWR);
1194
1195fail:
1196 if (stt) {
1197 for (i = 0; i < npages; i++)
1198 if (stt->pages[i])
1199 __free_page(stt->pages[i]);
1200
1201 kfree(stt);
1202 }
1203 return ret;
1204}
1205 1096
1206/* Work out RMLS (real mode limit selector) field value for a given RMA size. 1097/* Work out RMLS (real mode limit selector) field value for a given RMA size.
1207 Assumes POWER7 or PPC970. */ 1098 Assumes POWER7 or PPC970. */
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index d169a0aa4887..815ac5938a9e 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -1171,11 +1171,18 @@ void kvmppc_core_commit_memory_region(struct kvm *kvm,
1171 1171
1172int kvmppc_core_init_vm(struct kvm *kvm) 1172int kvmppc_core_init_vm(struct kvm *kvm)
1173{ 1173{
1174#ifdef CONFIG_PPC64
1175 INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
1176#endif
1177
1174 return 0; 1178 return 0;
1175} 1179}
1176 1180
1177void kvmppc_core_destroy_vm(struct kvm *kvm) 1181void kvmppc_core_destroy_vm(struct kvm *kvm)
1178{ 1182{
1183#ifdef CONFIG_PPC64
1184 WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables));
1185#endif
1179} 1186}
1180 1187
1181static int kvmppc_book3s_init(void) 1188static int kvmppc_book3s_init(void)
diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c
index 60ac0e793476..3ff9013d6e79 100644
--- a/arch/powerpc/kvm/book3s_pr_papr.c
+++ b/arch/powerpc/kvm/book3s_pr_papr.c
@@ -15,6 +15,8 @@
15 * published by the Free Software Foundation. 15 * published by the Free Software Foundation.
16 */ 16 */
17 17
18#include <linux/anon_inodes.h>
19
18#include <asm/uaccess.h> 20#include <asm/uaccess.h>
19#include <asm/kvm_ppc.h> 21#include <asm/kvm_ppc.h>
20#include <asm/kvm_book3s.h> 22#include <asm/kvm_book3s.h>
@@ -211,6 +213,20 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
211 return EMULATE_DONE; 213 return EMULATE_DONE;
212} 214}
213 215
216static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
217{
218 unsigned long liobn = kvmppc_get_gpr(vcpu, 4);
219 unsigned long ioba = kvmppc_get_gpr(vcpu, 5);
220 unsigned long tce = kvmppc_get_gpr(vcpu, 6);
221 long rc;
222
223 rc = kvmppc_h_put_tce(vcpu, liobn, ioba, tce);
224 if (rc == H_TOO_HARD)
225 return EMULATE_FAIL;
226 kvmppc_set_gpr(vcpu, 3, rc);
227 return EMULATE_DONE;
228}
229
214int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) 230int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
215{ 231{
216 switch (cmd) { 232 switch (cmd) {
@@ -222,6 +238,8 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
222 return kvmppc_h_pr_protect(vcpu); 238 return kvmppc_h_pr_protect(vcpu);
223 case H_BULK_REMOVE: 239 case H_BULK_REMOVE:
224 return kvmppc_h_pr_bulk_remove(vcpu); 240 return kvmppc_h_pr_bulk_remove(vcpu);
241 case H_PUT_TCE:
242 return kvmppc_h_pr_put_tce(vcpu);
225 case H_CEDE: 243 case H_CEDE:
226 kvm_vcpu_block(vcpu); 244 kvm_vcpu_block(vcpu);
227 clear_bit(KVM_REQ_UNHALT, &vcpu->requests); 245 clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 58ad8609bb43..6ac31154d170 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -244,10 +244,12 @@ int kvm_dev_ioctl_check_extension(long ext)
244 r = KVM_COALESCED_MMIO_PAGE_OFFSET; 244 r = KVM_COALESCED_MMIO_PAGE_OFFSET;
245 break; 245 break;
246#endif 246#endif
247#ifdef CONFIG_KVM_BOOK3S_64_HV 247#ifdef CONFIG_PPC_BOOK3S_64
248 case KVM_CAP_SPAPR_TCE: 248 case KVM_CAP_SPAPR_TCE:
249 r = 1; 249 r = 1;
250 break; 250 break;
251#endif /* CONFIG_PPC_BOOK3S_64 */
252#ifdef CONFIG_KVM_BOOK3S_64_HV
251 case KVM_CAP_PPC_SMT: 253 case KVM_CAP_PPC_SMT:
252 r = threads_per_core; 254 r = threads_per_core;
253 break; 255 break;
@@ -773,7 +775,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
773 775
774 break; 776 break;
775 } 777 }
776#ifdef CONFIG_KVM_BOOK3S_64_HV 778#ifdef CONFIG_PPC_BOOK3S_64
777 case KVM_CREATE_SPAPR_TCE: { 779 case KVM_CREATE_SPAPR_TCE: {
778 struct kvm_create_spapr_tce create_tce; 780 struct kvm_create_spapr_tce create_tce;
779 struct kvm *kvm = filp->private_data; 781 struct kvm *kvm = filp->private_data;
@@ -784,7 +786,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
784 r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce); 786 r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce);
785 goto out; 787 goto out;
786 } 788 }
789#endif /* CONFIG_PPC_BOOK3S_64 */
787 790
791#ifdef CONFIG_KVM_BOOK3S_64_HV
788 case KVM_ALLOCATE_RMA: { 792 case KVM_ALLOCATE_RMA: {
789 struct kvm *kvm = filp->private_data; 793 struct kvm *kvm = filp->private_data;
790 struct kvm_allocate_rma rma; 794 struct kvm_allocate_rma rma;