aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-07-29 08:48:06 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:50:57 -0400
commit644bfa013fd589b0df2470a66bcd104318ef24cd (patch)
tree7789aae3ec11b1ca49050e3afaf004fe0ea6c8b4 /arch/powerpc
parent7810927760a0d16d7a41be4dab895fbbf9445bc0 (diff)
KVM: PPC: PV wrteei
On BookE the preferred way to write the EE bit is the wrteei instruction. It already encodes the EE bit in the instruction. So in order to get BookE some speedups as well, let's also PV'nize thati instruction. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/kvm.c50
-rw-r--r--arch/powerpc/kernel/kvm_emul.S41
2 files changed, 91 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 8ac57e2c52fa..e93681753deb 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -67,6 +67,9 @@
67#define KVM_INST_MTMSRD_L1 0x7c010164 67#define KVM_INST_MTMSRD_L1 0x7c010164
68#define KVM_INST_MTMSR 0x7c000124 68#define KVM_INST_MTMSR 0x7c000124
69 69
70#define KVM_INST_WRTEEI_0 0x7c000146
71#define KVM_INST_WRTEEI_1 0x7c008146
72
70static bool kvm_patching_worked = true; 73static bool kvm_patching_worked = true;
71static char kvm_tmp[1024 * 1024]; 74static char kvm_tmp[1024 * 1024];
72static int kvm_tmp_index; 75static int kvm_tmp_index;
@@ -221,6 +224,47 @@ static void kvm_patch_ins_mtmsr(u32 *inst, u32 rt)
221 kvm_patch_ins_b(inst, distance_start); 224 kvm_patch_ins_b(inst, distance_start);
222} 225}
223 226
227#ifdef CONFIG_BOOKE
228
229extern u32 kvm_emulate_wrteei_branch_offs;
230extern u32 kvm_emulate_wrteei_ee_offs;
231extern u32 kvm_emulate_wrteei_len;
232extern u32 kvm_emulate_wrteei[];
233
234static void kvm_patch_ins_wrteei(u32 *inst)
235{
236 u32 *p;
237 int distance_start;
238 int distance_end;
239 ulong next_inst;
240
241 p = kvm_alloc(kvm_emulate_wrteei_len * 4);
242 if (!p)
243 return;
244
245 /* Find out where we are and put everything there */
246 distance_start = (ulong)p - (ulong)inst;
247 next_inst = ((ulong)inst + 4);
248 distance_end = next_inst - (ulong)&p[kvm_emulate_wrteei_branch_offs];
249
250 /* Make sure we only write valid b instructions */
251 if (distance_start > KVM_INST_B_MAX) {
252 kvm_patching_worked = false;
253 return;
254 }
255
256 /* Modify the chunk to fit the invocation */
257 memcpy(p, kvm_emulate_wrteei, kvm_emulate_wrteei_len * 4);
258 p[kvm_emulate_wrteei_branch_offs] |= distance_end & KVM_INST_B_MASK;
259 p[kvm_emulate_wrteei_ee_offs] |= (*inst & MSR_EE);
260 flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrteei_len * 4);
261
262 /* Patch the invocation */
263 kvm_patch_ins_b(inst, distance_start);
264}
265
266#endif
267
224static void kvm_map_magic_page(void *data) 268static void kvm_map_magic_page(void *data)
225{ 269{
226 kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE, 270 kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -310,6 +354,12 @@ static void kvm_check_ins(u32 *inst)
310 } 354 }
311 355
312 switch (_inst) { 356 switch (_inst) {
357#ifdef CONFIG_BOOKE
358 case KVM_INST_WRTEEI_0:
359 case KVM_INST_WRTEEI_1:
360 kvm_patch_ins_wrteei(inst);
361 break;
362#endif
313 } 363 }
314} 364}
315 365
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S
index 8cd22f47dd01..3199f65ede2c 100644
--- a/arch/powerpc/kernel/kvm_emul.S
+++ b/arch/powerpc/kernel/kvm_emul.S
@@ -204,3 +204,44 @@ kvm_emulate_mtmsr_orig_ins_offs:
204.global kvm_emulate_mtmsr_len 204.global kvm_emulate_mtmsr_len
205kvm_emulate_mtmsr_len: 205kvm_emulate_mtmsr_len:
206 .long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4 206 .long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4
207
208
209
210.global kvm_emulate_wrteei
211kvm_emulate_wrteei:
212
213 SCRATCH_SAVE
214
215 /* Fetch old MSR in r31 */
216 LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
217
218 /* Remove MSR_EE from old MSR */
219 li r30, 0
220 ori r30, r30, MSR_EE
221 andc r31, r31, r30
222
223 /* OR new MSR_EE onto the old MSR */
224kvm_emulate_wrteei_ee:
225 ori r31, r31, 0
226
227 /* Write new MSR value back */
228 STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
229
230 SCRATCH_RESTORE
231
232 /* Go back to caller */
233kvm_emulate_wrteei_branch:
234 b .
235kvm_emulate_wrteei_end:
236
237.global kvm_emulate_wrteei_branch_offs
238kvm_emulate_wrteei_branch_offs:
239 .long (kvm_emulate_wrteei_branch - kvm_emulate_wrteei) / 4
240
241.global kvm_emulate_wrteei_ee_offs
242kvm_emulate_wrteei_ee_offs:
243 .long (kvm_emulate_wrteei_ee - kvm_emulate_wrteei) / 4
244
245.global kvm_emulate_wrteei_len
246kvm_emulate_wrteei_len:
247 .long (kvm_emulate_wrteei_end - kvm_emulate_wrteei) / 4