#define PPC_INST_ISEL                  0x7c00001e
 #define PPC_INST_ISEL_MASK             0xfc00003e
 #define PPC_INST_LDARX                 0x7c0000a8
+#define PPC_INST_LOGMPP                        0x7c0007e4
 #define PPC_INST_LSWI                  0x7c0004aa
 #define PPC_INST_LSWX                  0x7c00042a
 #define PPC_INST_LWARX                 0x7c000028
 #define __PPC_EH(eh)   0
 #endif
 
+/* POWER8 Micro Partition Prefetch (MPP) parameters */
+/* Address mask is common for LOGMPP instruction and MPPR SPR */
+#define PPC_MPPE_ADDRESS_MASK 0xffffffffc000
+
+/* Bits 60 and 61 of MPP SPR should be set to one of the following */
+/* Aborting the fetch is indeed setting 00 in the table size bits */
+#define PPC_MPPR_FETCH_ABORT (0x0ULL << 60)
+#define PPC_MPPR_FETCH_WHOLE_TABLE (0x2ULL << 60)
+
+/* Bits 54 and 55 of register for LOGMPP instruction should be set to: */
+#define PPC_LOGMPP_LOG_L2 (0x02ULL << 54)
+#define PPC_LOGMPP_LOG_L2L3 (0x01ULL << 54)
+#define PPC_LOGMPP_LOG_ABORT (0x03ULL << 54)
+
 /* Deal with instructions that older assemblers aren't aware of */
 #define        PPC_DCBAL(a, b)         stringify_in_c(.long PPC_INST_DCBAL | \
                                        __PPC_RA(a) | __PPC_RB(b))
 #define PPC_LDARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LDARX | \
                                        ___PPC_RT(t) | ___PPC_RA(a) | \
                                        ___PPC_RB(b) | __PPC_EH(eh))
+#define PPC_LOGMPP(b)          stringify_in_c(.long PPC_INST_LOGMPP | \
+                                       __PPC_RB(b))
 #define PPC_LWARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LWARX | \
                                        ___PPC_RT(t) | ___PPC_RA(a) | \
                                        ___PPC_RB(b) | __PPC_EH(eh))
 
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
+#include <asm/cache.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/uaccess.h>
 
 static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
 
+#if defined(CONFIG_PPC_64K_PAGES)
+#define MPP_BUFFER_ORDER       0
+#elif defined(CONFIG_PPC_4K_PAGES)
+#define MPP_BUFFER_ORDER       3
+#endif
+
+
 static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
 
        vcore->first_vcpuid = core * threads_per_subcore;
        vcore->kvm = kvm;
 
+       vcore->mpp_buffer_is_valid = false;
+
+       if (cpu_has_feature(CPU_FTR_ARCH_207S))
+               vcore->mpp_buffer = (void *)__get_free_pages(
+                       GFP_KERNEL|__GFP_ZERO,
+                       MPP_BUFFER_ORDER);
+
        return vcore;
 }
 
        return 1;
 }
 
+static void kvmppc_start_saving_l2_cache(struct kvmppc_vcore *vc)
+{
+       phys_addr_t phy_addr, mpp_addr;
+
+       phy_addr = (phys_addr_t)virt_to_phys(vc->mpp_buffer);
+       mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
+
+       mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_ABORT);
+       logmpp(mpp_addr | PPC_LOGMPP_LOG_L2);
+
+       vc->mpp_buffer_is_valid = true;
+}
+
+static void kvmppc_start_restoring_l2_cache(const struct kvmppc_vcore *vc)
+{
+       phys_addr_t phy_addr, mpp_addr;
+
+       phy_addr = virt_to_phys(vc->mpp_buffer);
+       mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
+
+       /* We must abort any in-progress save operations to ensure
+        * the table is valid so that prefetch engine knows when to
+        * stop prefetching. */
+       logmpp(mpp_addr | PPC_LOGMPP_LOG_ABORT);
+       mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_WHOLE_TABLE);
+}
+
 /*
  * Run a set of guest threads on a physical core.
  * Called with vc->lock held.
 
        srcu_idx = srcu_read_lock(&vc->kvm->srcu);
 
+       if (vc->mpp_buffer_is_valid)
+               kvmppc_start_restoring_l2_cache(vc);
+
        __kvmppc_vcore_entry();
 
        spin_lock(&vc->lock);
+
+       if (vc->mpp_buffer)
+               kvmppc_start_saving_l2_cache(vc);
+
        /* disable sending of IPIs on virtual external irqs */
        list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
                vcpu->cpu = -1;
 {
        long int i;
 
-       for (i = 0; i < KVM_MAX_VCORES; ++i)
+       for (i = 0; i < KVM_MAX_VCORES; ++i) {
+               if (kvm->arch.vcores[i] && kvm->arch.vcores[i]->mpp_buffer) {
+                       struct kvmppc_vcore *vc = kvm->arch.vcores[i];
+                       free_pages((unsigned long)vc->mpp_buffer,
+                                  MPP_BUFFER_ORDER);
+               }
                kfree(kvm->arch.vcores[i]);
+       }
        kvm->arch.online_vcores = 0;
 }