@@ -144,5 +144,6 @@ static inline ulong dsisr(void)
extern void kvm_return_point(void);
#define INS_DCBZ 0x7c0007ec
+#define INS_BLR 0x4e800020
#endif /* __ASM_KVM_BOOK3S_H__ */
@@ -103,6 +103,10 @@ extern void kvmppc_booke_exit(void);
extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu);
+/* 16*NR_CPUS bytes filled with "blr" instructions. We use this to enable
+ code to execute arbitrary (checked!) opcodes. */
+extern u32 *kvmppc_call_stack;
+
/*
* Cuts out inst bits with ordering according to spec.
* That means the leftmost bit is zero. All given bits are included.
@@ -35,6 +35,8 @@
/* #define EXIT_DEBUG_SIMPLE */
/* #define DEBUG_EXT */
+u32 *kvmppc_call_stack;
+
static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
ulong msr);
@@ -1249,7 +1251,17 @@ int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
static int kvmppc_book3s_init(void)
{
- return kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), THIS_MODULE);
+ int r, i;
+
+ r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), THIS_MODULE);
+
+ /* Prepare call blob we can use to execute single instructions */
+ kvmppc_call_stack = __vmalloc(NR_CPUS * 2 * sizeof(u32),
+ GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC);
+ for (i = 0; i < (NR_CPUS * 2); i++)
+ kvmppc_call_stack[i] = INS_BLR;
+
+ return r;
}
static void kvmppc_book3s_exit(void)