aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/kvm.c
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/kernel/kvm.c
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/kernel/kvm.c')
-rw-r--r--arch/powerpc/kernel/kvm.c50
1 files changed, 50 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