KVM: PPC: PV assembler helpers
authorAlexander Graf <agraf@suse.de>
Thu, 29 Jul 2010 12:48:03 +0000 (14:48 +0200)
committerAvi Kivity <avi@redhat.com>
Sun, 24 Oct 2010 08:50:55 +0000 (10:50 +0200)
When we hook an instruction we need to make sure we don't clobber any of
the registers at that point. So we write them out to scratch space in the
magic page. To make sure we don't fall into a race with another piece of
hooked code, we need to disable interrupts.

To make the later patches and code in general easier readable, let's introduce
a set of defines that save and restore r30, r31 and cr. Let's also define some
helpers to read the lower 32 bits of a 64 bit field on 32 bit systems.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Avi Kivity <avi@redhat.com>
arch/powerpc/kernel/kvm_emul.S

index 5cfa2ae..1dac72d 100644 (file)
@@ -34,3 +34,33 @@ kvm_hypercall_start:
        blr
 
 #define KVM_MAGIC_PAGE         (-4096)
+
+#ifdef CONFIG_64BIT
+#define LL64(reg, offs, reg2)  ld      reg, (offs)(reg2)
+#define STL64(reg, offs, reg2) std     reg, (offs)(reg2)
+#else
+#define LL64(reg, offs, reg2)  lwz     reg, (offs + 4)(reg2)
+#define STL64(reg, offs, reg2) stw     reg, (offs + 4)(reg2)
+#endif
+
+#define SCRATCH_SAVE                                                   \
+       /* Enable critical section. We are critical if                  \
+          shared->critical == r1 */                                    \
+       STL64(r1, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);              \
+                                                                       \
+       /* Save state */                                                \
+       PPC_STL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0);          \
+       PPC_STL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0);          \
+       mfcr    r31;                                                    \
+       stw     r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);
+
+#define SCRATCH_RESTORE                                                        \
+       /* Restore state */                                             \
+       PPC_LL  r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0);          \
+       lwz     r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0);          \
+       mtcr    r30;                                                    \
+       PPC_LL  r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0);          \
+                                                                       \
+       /* Disable critical section. We are critical if                 \
+          shared->critical == r1 and r2 is always != r1 */             \
+       STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);