KVM: PPC: Make shared struct aka magic page guest endian
authorAlexander Graf <agraf@suse.de>
Thu, 24 Apr 2014 11:46:24 +0000 (13:46 +0200)
committerAlexander Graf <agraf@suse.de>
Fri, 30 May 2014 12:26:21 +0000 (14:26 +0200)
The shared (magic) page is a data structure that contains often used
supervisor privileged SPRs accessible via memory to the user to reduce
the number of exits we have to take to read/write them.

When we actually share this structure with the guest we have to maintain
it in guest endianness, because some of the patch tricks only work with
native endian load/store operations.

Since we only share the structure with either host or guest in little
endian on book3s_64 pr mode, we don't have to worry about booke or book3s hv.

For booke, the shared struct stays big endian. For book3s_64 hv we maintain
the struct in host native endian, since it never gets shared with the guest.

For book3s_64 pr we introduce a variable that tells us which endianness the
shared struct is in and route every access to it through helper inline
functions that evaluate this variable.

Signed-off-by: Alexander Graf <agraf@suse.de>
20 files changed:
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_booke.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_32_mmu.c
arch/powerpc/kvm/book3s_32_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu.c
arch/powerpc/kvm/book3s_64_mmu_host.c
arch/powerpc/kvm/book3s_emulate.c
arch/powerpc/kvm/book3s_exports.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/book3s_paired_singles.c
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/book3s_pr_papr.c
arch/powerpc/kvm/emulate.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/kvm/trace_pr.h

index bb1e38a23ac76753cb24162b07a7c03a517f7126..f52f65694527ea7b42ceb1df485039fc9abba623 100644 (file)
@@ -268,9 +268,10 @@ static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
        return vcpu->arch.pc;
 }
 
+static inline u64 kvmppc_get_msr(struct kvm_vcpu *vcpu);
 static inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu)
 {
-       return (vcpu->arch.shared->msr & MSR_LE) != (MSR_KERNEL & MSR_LE);
+       return (kvmppc_get_msr(vcpu) & MSR_LE) != (MSR_KERNEL & MSR_LE);
 }
 
 static inline u32 kvmppc_get_last_inst_internal(struct kvm_vcpu *vcpu, ulong pc)
index 80d46b5a7efb49cc6de436e45da6b0b5e690d9cf..c7aed6105ff98901fba31e5771ae9b6257107ee6 100644 (file)
@@ -108,9 +108,4 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.fault_dear;
 }
-
-static inline ulong kvmppc_get_msr(struct kvm_vcpu *vcpu)
-{
-       return vcpu->arch.shared->msr;
-}
 #endif /* __ASM_KVM_BOOKE_H__ */
index d342f8efc8435e0da5b165c3ee299d97664d22c2..15f19d3cc584366504877f93836b43b025d86870 100644 (file)
@@ -623,6 +623,9 @@ struct kvm_vcpu_arch {
        wait_queue_head_t cpu_run;
 
        struct kvm_vcpu_arch_shared *shared;
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
+       bool shared_big_endian;
+#endif
        unsigned long magic_page_pa; /* phys addr to map the magic page to */
        unsigned long magic_page_ea; /* effect. addr to map the magic page to */
 
index 4096f16502a9becab431cb8e3f7c9f51b6989b4f..4a7cc453be0b0b8193a52a9900d71eea3d2d27fc 100644 (file)
@@ -448,6 +448,84 @@ static inline void kvmppc_mmu_flush_icache(pfn_t pfn)
        }
 }
 
+/*
+ * Shared struct helpers. The shared struct can be little or big endian,
+ * depending on the guest endianness. So expose helpers to all of them.
+ */
+static inline bool kvmppc_shared_big_endian(struct kvm_vcpu *vcpu)
+{
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
+       /* Only Book3S_64 PR supports bi-endian for now */
+       return vcpu->arch.shared_big_endian;
+#elif defined(CONFIG_PPC_BOOK3S_64) && defined(__LITTLE_ENDIAN__)
+       /* Book3s_64 HV on little endian is always little endian */
+       return false;
+#else
+       return true;
+#endif
+}
+
+#define SHARED_WRAPPER_GET(reg, size)                                  \
+static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu)  \
+{                                                                      \
+       if (kvmppc_shared_big_endian(vcpu))                             \
+              return be##size##_to_cpu(vcpu->arch.shared->reg);        \
+       else                                                            \
+              return le##size##_to_cpu(vcpu->arch.shared->reg);        \
+}                                                                      \
+
+#define SHARED_WRAPPER_SET(reg, size)                                  \
+static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val)        \
+{                                                                      \
+       if (kvmppc_shared_big_endian(vcpu))                             \
+              vcpu->arch.shared->reg = cpu_to_be##size(val);           \
+       else                                                            \
+              vcpu->arch.shared->reg = cpu_to_le##size(val);           \
+}                                                                      \
+
+#define SHARED_WRAPPER(reg, size)                                      \
+       SHARED_WRAPPER_GET(reg, size)                                   \
+       SHARED_WRAPPER_SET(reg, size)                                   \
+
+SHARED_WRAPPER(critical, 64)
+SHARED_WRAPPER(sprg0, 64)
+SHARED_WRAPPER(sprg1, 64)
+SHARED_WRAPPER(sprg2, 64)
+SHARED_WRAPPER(sprg3, 64)
+SHARED_WRAPPER(srr0, 64)
+SHARED_WRAPPER(srr1, 64)
+SHARED_WRAPPER(dar, 64)
+SHARED_WRAPPER_GET(msr, 64)
+static inline void kvmppc_set_msr_fast(struct kvm_vcpu *vcpu, u64 val)
+{
+       if (kvmppc_shared_big_endian(vcpu))
+              vcpu->arch.shared->msr = cpu_to_be64(val);
+       else
+              vcpu->arch.shared->msr = cpu_to_le64(val);
+}
+SHARED_WRAPPER(dsisr, 32)
+SHARED_WRAPPER(int_pending, 32)
+SHARED_WRAPPER(sprg4, 64)
+SHARED_WRAPPER(sprg5, 64)
+SHARED_WRAPPER(sprg6, 64)
+SHARED_WRAPPER(sprg7, 64)
+
+static inline u32 kvmppc_get_sr(struct kvm_vcpu *vcpu, int nr)
+{
+       if (kvmppc_shared_big_endian(vcpu))
+              return be32_to_cpu(vcpu->arch.shared->sr[nr]);
+       else
+              return le32_to_cpu(vcpu->arch.shared->sr[nr]);
+}
+
+static inline void kvmppc_set_sr(struct kvm_vcpu *vcpu, int nr, u32 val)
+{
+       if (kvmppc_shared_big_endian(vcpu))
+              vcpu->arch.shared->sr[nr] = cpu_to_be32(val);
+       else
+              vcpu->arch.shared->sr[nr] = cpu_to_le32(val);
+}
+
 /*
  * Please call after prepare_to_enter. This function puts the lazy ee and irq
  * disabled tracking state back to normal mode, without actually enabling
@@ -485,7 +563,7 @@ static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
        msr_64bit = MSR_SF;
 #endif
 
-       if (!(vcpu->arch.shared->msr & msr_64bit))
+       if (!(kvmppc_get_msr(vcpu) & msr_64bit))
                ea = (uint32_t)ea;
 
        return ea;
index 6a4b77d197f37f2a0ebaccc3d6f65b0a9040c46a..bbf3b9a3e2af87c607dc1e83b55b578b4b9d8a48 100644 (file)
@@ -54,6 +54,7 @@
 #endif
 #if defined(CONFIG_KVM) && defined(CONFIG_PPC_BOOK3S)
 #include <asm/kvm_book3s.h>
+#include <asm/kvm_ppc.h>
 #endif
 
 #ifdef CONFIG_PPC32
@@ -467,6 +468,9 @@ int main(void)
        DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
        DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
        DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr));
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
+       DEFINE(VCPU_SHAREDBE, offsetof(struct kvm_vcpu, arch.shared_big_endian));
+#endif
 
        DEFINE(VCPU_SHARED_MAS0, offsetof(struct kvm_vcpu_arch_shared, mas0));
        DEFINE(VCPU_SHARED_MAS1, offsetof(struct kvm_vcpu_arch_shared, mas1));
index 94e597e6f15cd08f3f4f7deb5bab73d2d3ff1f27..81abc5cef0fea1259674ebaf2b367a9630bbb918 100644 (file)
@@ -85,9 +85,9 @@ static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
        if (is_kvmppc_hv_enabled(vcpu->kvm))
                return;
        if (pending_now)
-               vcpu->arch.shared->int_pending = 1;
+               kvmppc_set_int_pending(vcpu, 1);
        else if (old_pending)
-               vcpu->arch.shared->int_pending = 0;
+               kvmppc_set_int_pending(vcpu, 0);
 }
 
 static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
@@ -99,11 +99,11 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
        if (is_kvmppc_hv_enabled(vcpu->kvm))
                return false;
 
-       crit_raw = vcpu->arch.shared->critical;
+       crit_raw = kvmppc_get_critical(vcpu);
        crit_r1 = kvmppc_get_gpr(vcpu, 1);
 
        /* Truncate crit indicators in 32 bit mode */
-       if (!(vcpu->arch.shared->msr & MSR_SF)) {
+       if (!(kvmppc_get_msr(vcpu) & MSR_SF)) {
                crit_raw &= 0xffffffff;
                crit_r1 &= 0xffffffff;
        }
@@ -111,15 +111,15 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
        /* Critical section when crit == r1 */
        crit = (crit_raw == crit_r1);
        /* ... and we're in supervisor mode */
-       crit = crit && !(vcpu->arch.shared->msr & MSR_PR);
+       crit = crit && !(kvmppc_get_msr(vcpu) & MSR_PR);
 
        return crit;
 }
 
 void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
 {
-       vcpu->arch.shared->srr0 = kvmppc_get_pc(vcpu);
-       vcpu->arch.shared->srr1 = vcpu->arch.shared->msr | flags;
+       kvmppc_set_srr0(vcpu, kvmppc_get_pc(vcpu));
+       kvmppc_set_srr1(vcpu, kvmppc_get_msr(vcpu) | flags);
        kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec);
        vcpu->arch.mmu.reset_msr(vcpu);
 }
@@ -225,12 +225,12 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
 
        switch (priority) {
        case BOOK3S_IRQPRIO_DECREMENTER:
-               deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
+               deliver = (kvmppc_get_msr(vcpu) & MSR_EE) && !crit;
                vec = BOOK3S_INTERRUPT_DECREMENTER;
                break;
        case BOOK3S_IRQPRIO_EXTERNAL:
        case BOOK3S_IRQPRIO_EXTERNAL_LEVEL:
-               deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
+               deliver = (kvmppc_get_msr(vcpu) & MSR_EE) && !crit;
                vec = BOOK3S_INTERRUPT_EXTERNAL;
                break;
        case BOOK3S_IRQPRIO_SYSTEM_RESET:
@@ -343,7 +343,7 @@ pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing,
 {
        ulong mp_pa = vcpu->arch.magic_page_pa;
 
-       if (!(vcpu->arch.shared->msr & MSR_SF))
+       if (!(kvmppc_get_msr(vcpu) & MSR_SF))
                mp_pa = (uint32_t)mp_pa;
 
        /* Magic page override */
@@ -367,7 +367,7 @@ EXPORT_SYMBOL_GPL(kvmppc_gfn_to_pfn);
 static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
                        bool iswrite, struct kvmppc_pte *pte)
 {
-       int relocated = (vcpu->arch.shared->msr & (data ? MSR_DR : MSR_IR));
+       int relocated = (kvmppc_get_msr(vcpu) & (data ? MSR_DR : MSR_IR));
        int r;
 
        if (relocated) {
@@ -498,18 +498,18 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
        regs->ctr = kvmppc_get_ctr(vcpu);
        regs->lr = kvmppc_get_lr(vcpu);
        regs->xer = kvmppc_get_xer(vcpu);
-       regs->msr = vcpu->arch.shared->msr;
-       regs->srr0 = vcpu->arch.shared->srr0;
-       regs->srr1 = vcpu->arch.shared->srr1;
+       regs->msr = kvmppc_get_msr(vcpu);
+       regs->srr0 = kvmppc_get_srr0(vcpu);
+       regs->srr1 = kvmppc_get_srr1(vcpu);
        regs->pid = vcpu->arch.pid;
-       regs->sprg0 = vcpu->arch.shared->sprg0;
-       regs->sprg1 = vcpu->arch.shared->sprg1;
-       regs->sprg2 = vcpu->arch.shared->sprg2;
-       regs->sprg3 = vcpu->arch.shared->sprg3;
-       regs->sprg4 = vcpu->arch.shared->sprg4;
-       regs->sprg5 = vcpu->arch.shared->sprg5;
-       regs->sprg6 = vcpu->arch.shared->sprg6;
-       regs->sprg7 = vcpu->arch.shared->sprg7;
+       regs->sprg0 = kvmppc_get_sprg0(vcpu);
+       regs->sprg1 = kvmppc_get_sprg1(vcpu);
+       regs->sprg2 = kvmppc_get_sprg2(vcpu);
+       regs->sprg3 = kvmppc_get_sprg3(vcpu);
+       regs->sprg4 = kvmppc_get_sprg4(vcpu);
+       regs->sprg5 = kvmppc_get_sprg5(vcpu);
+       regs->sprg6 = kvmppc_get_sprg6(vcpu);
+       regs->sprg7 = kvmppc_get_sprg7(vcpu);
 
        for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
                regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
@@ -527,16 +527,16 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
        kvmppc_set_lr(vcpu, regs->lr);
        kvmppc_set_xer(vcpu, regs->xer);
        kvmppc_set_msr(vcpu, regs->msr);
-       vcpu->arch.shared->srr0 = regs->srr0;
-       vcpu->arch.shared->srr1 = regs->srr1;
-       vcpu->arch.shared->sprg0 = regs->sprg0;
-       vcpu->arch.shared->sprg1 = regs->sprg1;
-       vcpu->arch.shared->sprg2 = regs->sprg2;
-       vcpu->arch.shared->sprg3 = regs->sprg3;
-       vcpu->arch.shared->sprg4 = regs->sprg4;
-       vcpu->arch.shared->sprg5 = regs->sprg5;
-       vcpu->arch.shared->sprg6 = regs->sprg6;
-       vcpu->arch.shared->sprg7 = regs->sprg7;
+       kvmppc_set_srr0(vcpu, regs->srr0);
+       kvmppc_set_srr1(vcpu, regs->srr1);
+       kvmppc_set_sprg0(vcpu, regs->sprg0);
+       kvmppc_set_sprg1(vcpu, regs->sprg1);
+       kvmppc_set_sprg2(vcpu, regs->sprg2);
+       kvmppc_set_sprg3(vcpu, regs->sprg3);
+       kvmppc_set_sprg4(vcpu, regs->sprg4);
+       kvmppc_set_sprg5(vcpu, regs->sprg5);
+       kvmppc_set_sprg6(vcpu, regs->sprg6);
+       kvmppc_set_sprg7(vcpu, regs->sprg7);
 
        for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
                kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
@@ -570,10 +570,10 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
                r = 0;
                switch (reg->id) {
                case KVM_REG_PPC_DAR:
-                       val = get_reg_val(reg->id, vcpu->arch.shared->dar);
+                       val = get_reg_val(reg->id, kvmppc_get_dar(vcpu));
                        break;
                case KVM_REG_PPC_DSISR:
-                       val = get_reg_val(reg->id, vcpu->arch.shared->dsisr);
+                       val = get_reg_val(reg->id, kvmppc_get_dsisr(vcpu));
                        break;
                case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
                        i = reg->id - KVM_REG_PPC_FPR0;
@@ -660,10 +660,10 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
                r = 0;
                switch (reg->id) {
                case KVM_REG_PPC_DAR:
-                       vcpu->arch.shared->dar = set_reg_val(reg->id, val);
+                       kvmppc_set_dar(vcpu, set_reg_val(reg->id, val));
                        break;
                case KVM_REG_PPC_DSISR:
-                       vcpu->arch.shared->dsisr = set_reg_val(reg->id, val);
+                       kvmppc_set_dsisr(vcpu, set_reg_val(reg->id, val));
                        break;
                case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
                        i = reg->id - KVM_REG_PPC_FPR0;
index 0e42b167da0be574fc166dec63d8266054bbdb65..628d90ed417d06e1d93d3f5ab919a6b4d050ce12 100644 (file)
@@ -91,7 +91,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
 
 static u32 find_sr(struct kvm_vcpu *vcpu, gva_t eaddr)
 {
-       return vcpu->arch.shared->sr[(eaddr >> 28) & 0xf];
+       return kvmppc_get_sr(vcpu, (eaddr >> 28) & 0xf);
 }
 
 static u64 kvmppc_mmu_book3s_32_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr,
@@ -160,7 +160,7 @@ static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr,
                else
                        bat = &vcpu_book3s->ibat[i];
 
-               if (vcpu->arch.shared->msr & MSR_PR) {
+               if (kvmppc_get_msr(vcpu) & MSR_PR) {
                        if (!bat->vp)
                                continue;
                } else {
@@ -242,8 +242,8 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
                        pte->raddr = (pte1 & ~(0xFFFULL)) | (eaddr & 0xFFF);
                        pp = pte1 & 3;
 
-                       if ((sr_kp(sre) &&  (vcpu->arch.shared->msr & MSR_PR)) ||
-                           (sr_ks(sre) && !(vcpu->arch.shared->msr & MSR_PR)))
+                       if ((sr_kp(sre) &&  (kvmppc_get_msr(vcpu) & MSR_PR)) ||
+                           (sr_ks(sre) && !(kvmppc_get_msr(vcpu) & MSR_PR)))
                                pp |= 4;
 
                        pte->may_write = false;
@@ -320,7 +320,7 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
        /* Magic page override */
        if (unlikely(mp_ea) &&
            unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) &&
-           !(vcpu->arch.shared->msr & MSR_PR)) {
+           !(kvmppc_get_msr(vcpu) & MSR_PR)) {
                pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data);
                pte->raddr = vcpu->arch.magic_page_pa | (pte->raddr & 0xfff);
                pte->raddr &= KVM_PAM;
@@ -345,13 +345,13 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
 
 static u32 kvmppc_mmu_book3s_32_mfsrin(struct kvm_vcpu *vcpu, u32 srnum)
 {
-       return vcpu->arch.shared->sr[srnum];
+       return kvmppc_get_sr(vcpu, srnum);
 }
 
 static void kvmppc_mmu_book3s_32_mtsrin(struct kvm_vcpu *vcpu, u32 srnum,
                                        ulong value)
 {
-       vcpu->arch.shared->sr[srnum] = value;
+       kvmppc_set_sr(vcpu, srnum, value);
        kvmppc_mmu_map_segment(vcpu, srnum << SID_SHIFT);
 }
 
@@ -371,8 +371,9 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
        ulong ea = esid << SID_SHIFT;
        u32 sr;
        u64 gvsid = esid;
+       u64 msr = kvmppc_get_msr(vcpu);
 
-       if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
+       if (msr & (MSR_DR|MSR_IR)) {
                sr = find_sr(vcpu, ea);
                if (sr_valid(sr))
                        gvsid = sr_vsid(sr);
@@ -381,7 +382,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
        /* In case we only have one of MSR_IR or MSR_DR set, let's put
           that in the real-mode context (and hope RM doesn't access
           high memory) */
-       switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
+       switch (msr & (MSR_DR|MSR_IR)) {
        case 0:
                *vsid = VSID_REAL | esid;
                break;
@@ -401,7 +402,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
                BUG();
        }
 
-       if (vcpu->arch.shared->msr & MSR_PR)
+       if (msr & MSR_PR)
                *vsid |= VSID_PR;
 
        return 0;
index 5fac89dfe4cdf2dd1673753d703dbf32c8b26b03..678e753704959775d85054293f10280843dd2339 100644 (file)
@@ -92,7 +92,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
        struct kvmppc_sid_map *map;
        u16 sid_map_mask;
 
-       if (vcpu->arch.shared->msr & MSR_PR)
+       if (kvmppc_get_msr(vcpu) & MSR_PR)
                gvsid |= VSID_PR;
 
        sid_map_mask = kvmppc_sid_hash(vcpu, gvsid);
@@ -279,7 +279,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
        u16 sid_map_mask;
        static int backwards_map = 0;
 
-       if (vcpu->arch.shared->msr & MSR_PR)
+       if (kvmppc_get_msr(vcpu) & MSR_PR)
                gvsid |= VSID_PR;
 
        /* We might get collisions that trap in preceding order, so let's
index b93c2456253db2bad11912060b021989464193bc..278729f4df80a6e4d07b21a1f9b6187894cc6410 100644 (file)
@@ -226,7 +226,7 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
        /* Magic page override */
        if (unlikely(mp_ea) &&
            unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) &&
-           !(vcpu->arch.shared->msr & MSR_PR)) {
+           !(kvmppc_get_msr(vcpu) & MSR_PR)) {
                gpte->eaddr = eaddr;
                gpte->vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, eaddr, data);
                gpte->raddr = vcpu->arch.magic_page_pa | (gpte->raddr & 0xfff);
@@ -269,9 +269,9 @@ do_second:
                goto no_page_found;
        }
 
-       if ((vcpu->arch.shared->msr & MSR_PR) && slbe->Kp)
+       if ((kvmppc_get_msr(vcpu) & MSR_PR) && slbe->Kp)
                key = 4;
-       else if (!(vcpu->arch.shared->msr & MSR_PR) && slbe->Ks)
+       else if (!(kvmppc_get_msr(vcpu) & MSR_PR) && slbe->Ks)
                key = 4;
 
        for (i=0; i<16; i+=2) {
@@ -482,7 +482,7 @@ static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu)
                vcpu->arch.slb[i].origv = 0;
        }
 
-       if (vcpu->arch.shared->msr & MSR_IR) {
+       if (kvmppc_get_msr(vcpu) & MSR_IR) {
                kvmppc_mmu_flush_segments(vcpu);
                kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
        }
@@ -566,7 +566,7 @@ static int segment_contains_magic_page(struct kvm_vcpu *vcpu, ulong esid)
 {
        ulong mp_ea = vcpu->arch.magic_page_ea;
 
-       return mp_ea && !(vcpu->arch.shared->msr & MSR_PR) &&
+       return mp_ea && !(kvmppc_get_msr(vcpu) & MSR_PR) &&
                (mp_ea >> SID_SHIFT) == esid;
 }
 #endif
@@ -579,8 +579,9 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
        u64 gvsid = esid;
        ulong mp_ea = vcpu->arch.magic_page_ea;
        int pagesize = MMU_PAGE_64K;
+       u64 msr = kvmppc_get_msr(vcpu);
 
-       if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
+       if (msr & (MSR_DR|MSR_IR)) {
                slb = kvmppc_mmu_book3s_64_find_slbe(vcpu, ea);
                if (slb) {
                        gvsid = slb->vsid;
@@ -593,7 +594,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
                }
        }
 
-       switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
+       switch (msr & (MSR_DR|MSR_IR)) {
        case 0:
                gvsid = VSID_REAL | esid;
                break;
@@ -626,7 +627,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
                gvsid |= VSID_64K;
 #endif
 
-       if (vcpu->arch.shared->msr & MSR_PR)
+       if (kvmppc_get_msr(vcpu) & MSR_PR)
                gvsid |= VSID_PR;
 
        *vsid = gvsid;
@@ -636,7 +637,7 @@ no_slb:
        /* Catch magic page case */
        if (unlikely(mp_ea) &&
            unlikely(esid == (mp_ea >> SID_SHIFT)) &&
-           !(vcpu->arch.shared->msr & MSR_PR)) {
+           !(kvmppc_get_msr(vcpu) & MSR_PR)) {
                *vsid = VSID_REAL | esid;
                return 0;
        }
index 0d513af62bba179ad7ccd777bb3f1aa4217b1cb3..e2efb85c65a37b2af75c96cc6bf787e1f8973a91 100644 (file)
@@ -58,7 +58,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
        struct kvmppc_sid_map *map;
        u16 sid_map_mask;
 
-       if (vcpu->arch.shared->msr & MSR_PR)
+       if (kvmppc_get_msr(vcpu) & MSR_PR)
                gvsid |= VSID_PR;
 
        sid_map_mask = kvmppc_sid_hash(vcpu, gvsid);
@@ -230,7 +230,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
        u16 sid_map_mask;
        static int backwards_map = 0;
 
-       if (vcpu->arch.shared->msr & MSR_PR)
+       if (kvmppc_get_msr(vcpu) & MSR_PR)
                gvsid |= VSID_PR;
 
        /* We might get collisions that trap in preceding order, so let's
index 99d40f8977e8abcaaf54f499af4d15a1ae1f268e..45d0a805c3ca25ef1faba8ad8dac450e1fc77cf0 100644 (file)
@@ -80,7 +80,7 @@ static bool spr_allowed(struct kvm_vcpu *vcpu, enum priv_level level)
                return false;
 
        /* Limit user space to its own small SPR set */
-       if ((vcpu->arch.shared->msr & MSR_PR) && level > PRIV_PROBLEM)
+       if ((kvmppc_get_msr(vcpu) & MSR_PR) && level > PRIV_PROBLEM)
                return false;
 
        return true;
@@ -100,8 +100,8 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
                switch (get_xop(inst)) {
                case OP_19_XOP_RFID:
                case OP_19_XOP_RFI:
-                       kvmppc_set_pc(vcpu, vcpu->arch.shared->srr0);
-                       kvmppc_set_msr(vcpu, vcpu->arch.shared->srr1);
+                       kvmppc_set_pc(vcpu, kvmppc_get_srr0(vcpu));
+                       kvmppc_set_msr(vcpu, kvmppc_get_srr1(vcpu));
                        *advance = 0;
                        break;
 
@@ -113,16 +113,16 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
        case 31:
                switch (get_xop(inst)) {
                case OP_31_XOP_MFMSR:
-                       kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->msr);
+                       kvmppc_set_gpr(vcpu, rt, kvmppc_get_msr(vcpu));
                        break;
                case OP_31_XOP_MTMSRD:
                {
                        ulong rs_val = kvmppc_get_gpr(vcpu, rs);
                        if (inst & 0x10000) {
-                               ulong new_msr = vcpu->arch.shared->msr;
+                               ulong new_msr = kvmppc_get_msr(vcpu);
                                new_msr &= ~(MSR_RI | MSR_EE);
                                new_msr |= rs_val & (MSR_RI | MSR_EE);
-                               vcpu->arch.shared->msr = new_msr;
+                               kvmppc_set_msr_fast(vcpu, new_msr);
                        } else
                                kvmppc_set_msr(vcpu, rs_val);
                        break;
@@ -179,7 +179,7 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        ulong cmd = kvmppc_get_gpr(vcpu, 3);
                        int i;
 
-                       if ((vcpu->arch.shared->msr & MSR_PR) ||
+                       if ((kvmppc_get_msr(vcpu) & MSR_PR) ||
                            !vcpu->arch.papr_enabled) {
                                emulated = EMULATE_FAIL;
                                break;
@@ -261,14 +261,14 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
                                ra_val = kvmppc_get_gpr(vcpu, ra);
 
                        addr = (ra_val + rb_val) & ~31ULL;
-                       if (!(vcpu->arch.shared->msr & MSR_SF))
+                       if (!(kvmppc_get_msr(vcpu) & MSR_SF))
                                addr &= 0xffffffff;
                        vaddr = addr;
 
                        r = kvmppc_st(vcpu, &addr, 32, zeros, true);
                        if ((r == -ENOENT) || (r == -EPERM)) {
                                *advance = 0;
-                               vcpu->arch.shared->dar = vaddr;
+                               kvmppc_set_dar(vcpu, vaddr);
                                vcpu->arch.fault_dar = vaddr;
 
                                dsisr = DSISR_ISSTORE;
@@ -277,7 +277,7 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
                                else if (r == -EPERM)
                                        dsisr |= DSISR_PROTFAULT;
 
-                               vcpu->arch.shared->dsisr = dsisr;
+                               kvmppc_set_dsisr(vcpu, dsisr);
                                vcpu->arch.fault_dsisr = dsisr;
 
                                kvmppc_book3s_queue_irqprio(vcpu,
@@ -356,10 +356,10 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
                to_book3s(vcpu)->sdr1 = spr_val;
                break;
        case SPRN_DSISR:
-               vcpu->arch.shared->dsisr = spr_val;
+               kvmppc_set_dsisr(vcpu, spr_val);
                break;
        case SPRN_DAR:
-               vcpu->arch.shared->dar = spr_val;
+               kvmppc_set_dar(vcpu, spr_val);
                break;
        case SPRN_HIOR:
                to_book3s(vcpu)->hior = spr_val;
@@ -493,10 +493,10 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
                *spr_val = to_book3s(vcpu)->sdr1;
                break;
        case SPRN_DSISR:
-               *spr_val = vcpu->arch.shared->dsisr;
+               *spr_val = kvmppc_get_dsisr(vcpu);
                break;
        case SPRN_DAR:
-               *spr_val = vcpu->arch.shared->dar;
+               *spr_val = kvmppc_get_dar(vcpu);
                break;
        case SPRN_HIOR:
                *spr_val = to_book3s(vcpu)->hior;
index 20d4ea8e656d3eacf3202ef42f806168d44841f4..0d013fbc2e13f876588a3af04a7019a87d2d6da7 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/export.h>
+#include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
 
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
index 8227dba5af0f4f3ebd70c051530ce98fa4a6e30d..030821a414a821af6f1c5437edeadfb475788f55 100644 (file)
@@ -1280,6 +1280,17 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
                goto free_vcpu;
 
        vcpu->arch.shared = &vcpu->arch.shregs;
+#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
+       /*
+        * The shared struct is never shared on HV,
+        * so we can always use host endianness
+        */
+#ifdef __BIG_ENDIAN__
+       vcpu->arch.shared_big_endian = true;
+#else
+       vcpu->arch.shared_big_endian = false;
+#endif
+#endif
        vcpu->arch.mmcr[0] = MMCR0_FC;
        vcpu->arch.ctrl = CTRL_RUNLATCH;
        /* default to host PVR, since we can't spoof it */
index 3533c999194a3db8d835d570bd7f4d86bb494bbb..e2c29e381dc7096d13af053526e0d98cf951d08e 100644 (file)
@@ -104,8 +104,27 @@ kvm_start_lightweight:
        stb     r3, HSTATE_RESTORE_HID5(r13)
 
        /* Load up guest SPRG3 value, since it's user readable */
-       ld      r3, VCPU_SHARED(r4)
-       ld      r3, VCPU_SHARED_SPRG3(r3)
+       lwz     r3, VCPU_SHAREDBE(r4)
+       cmpwi   r3, 0
+       ld      r5, VCPU_SHARED(r4)
+       beq     sprg3_little_endian
+sprg3_big_endian:
+#ifdef __BIG_ENDIAN__
+       ld      r3, VCPU_SHARED_SPRG3(r5)
+#else
+       addi    r5, r5, VCPU_SHARED_SPRG3
+       ldbrx   r3, 0, r5
+#endif
+       b       after_sprg3_load
+sprg3_little_endian:
+#ifdef __LITTLE_ENDIAN__
+       ld      r3, VCPU_SHARED_SPRG3(r5)
+#else
+       addi    r5, r5, VCPU_SHARED_SPRG3
+       ldbrx   r3, 0, r5
+#endif
+
+after_sprg3_load:
        mtspr   SPRN_SPRG3, r3
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
index c1abd95063f47d56a2092c57352bc0fff7ff9632..6c8011fd57e621fd702dfd5bb1259d81e9718ada 100644 (file)
@@ -165,16 +165,18 @@ static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt)
 
 static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
 {
-       u64 dsisr;
-       struct kvm_vcpu_arch_shared *shared = vcpu->arch.shared;
+       u32 dsisr;
+       u64 msr = kvmppc_get_msr(vcpu);
 
-       shared->msr = kvmppc_set_field(shared->msr, 33, 36, 0);
-       shared->msr = kvmppc_set_field(shared->msr, 42, 47, 0);
-       shared->dar = eaddr;
+       msr = kvmppc_set_field(msr, 33, 36, 0);
+       msr = kvmppc_set_field(msr, 42, 47, 0);
+       kvmppc_set_msr(vcpu, msr);
+       kvmppc_set_dar(vcpu, eaddr);
        /* Page Fault */
        dsisr = kvmppc_set_field(0, 33, 33, 1);
        if (is_store)
-               shared->dsisr = kvmppc_set_field(dsisr, 38, 38, 1);
+               dsisr = kvmppc_set_field(dsisr, 38, 38, 1);
+       kvmppc_set_dsisr(vcpu, dsisr);
        kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE);
 }
 
@@ -660,7 +662,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
        if (!kvmppc_inst_is_paired_single(vcpu, inst))
                return EMULATE_FAIL;
 
-       if (!(vcpu->arch.shared->msr & MSR_FP)) {
+       if (!(kvmppc_get_msr(vcpu) & MSR_FP)) {
                kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL);
                return EMULATE_AGAIN;
        }
index d7b0ad2bffe476a3ae5ba8a2d34ddc3dc4ff0694..d424ca05376572c68717337dcc2f6468601412ff 100644 (file)
@@ -246,14 +246,15 @@ static void kvm_set_spte_hva_pr(struct kvm *kvm, unsigned long hva, pte_t pte)
 
 static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
 {
-       ulong smsr = vcpu->arch.shared->msr;
+       ulong guest_msr = kvmppc_get_msr(vcpu);
+       ulong smsr = guest_msr;
 
        /* Guest MSR values */
        smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_LE;
        /* Process MSR values */
        smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
        /* External providers the guest reserved */
-       smsr |= (vcpu->arch.shared->msr & vcpu->arch.guest_owned_ext);
+       smsr |= (guest_msr & vcpu->arch.guest_owned_ext);
        /* 64-bit Process MSR values */
 #ifdef CONFIG_PPC_BOOK3S_64
        smsr |= MSR_ISF | MSR_HV;
@@ -263,14 +264,14 @@ static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
 
 static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
 {
-       ulong old_msr = vcpu->arch.shared->msr;
+       ulong old_msr = kvmppc_get_msr(vcpu);
 
 #ifdef EXIT_DEBUG
        printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
 #endif
 
        msr &= to_book3s(vcpu)->msr_mask;
-       vcpu->arch.shared->msr = msr;
+       kvmppc_set_msr_fast(vcpu, msr);
        kvmppc_recalc_shadow_msr(vcpu);
 
        if (msr & MSR_POW) {
@@ -281,11 +282,11 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
 
                        /* Unset POW bit after we woke up */
                        msr &= ~MSR_POW;
-                       vcpu->arch.shared->msr = msr;
+                       kvmppc_set_msr_fast(vcpu, msr);
                }
        }
 
-       if ((vcpu->arch.shared->msr & (MSR_PR|MSR_IR|MSR_DR)) !=
+       if ((kvmppc_get_msr(vcpu) & (MSR_PR|MSR_IR|MSR_DR)) !=
                   (old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
                kvmppc_mmu_flush_segments(vcpu);
                kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
@@ -317,7 +318,7 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
        }
 
        /* Preload FPU if it's enabled */
-       if (vcpu->arch.shared->msr & MSR_FP)
+       if (kvmppc_get_msr(vcpu) & MSR_FP)
                kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
 }
 
@@ -438,7 +439,7 @@ static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
 {
        ulong mp_pa = vcpu->arch.magic_page_pa;
 
-       if (!(vcpu->arch.shared->msr & MSR_SF))
+       if (!(kvmppc_get_msr(vcpu) & MSR_SF))
                mp_pa = (uint32_t)mp_pa;
 
        if (unlikely(mp_pa) &&
@@ -459,8 +460,8 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
        int page_found = 0;
        struct kvmppc_pte pte;
        bool is_mmio = false;
-       bool dr = (vcpu->arch.shared->msr & MSR_DR) ? true : false;
-       bool ir = (vcpu->arch.shared->msr & MSR_IR) ? true : false;
+       bool dr = (kvmppc_get_msr(vcpu) & MSR_DR) ? true : false;
+       bool ir = (kvmppc_get_msr(vcpu) & MSR_IR) ? true : false;
        u64 vsid;
 
        relocated = data ? dr : ir;
@@ -480,7 +481,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                pte.page_size = MMU_PAGE_64K;
        }
 
-       switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
+       switch (kvmppc_get_msr(vcpu) & (MSR_DR|MSR_IR)) {
        case 0:
                pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
                break;
@@ -488,7 +489,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
        case MSR_IR:
                vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
 
-               if ((vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) == MSR_DR)
+               if ((kvmppc_get_msr(vcpu) & (MSR_DR|MSR_IR)) == MSR_DR)
                        pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12));
                else
                        pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12));
@@ -511,22 +512,25 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        if (page_found == -ENOENT) {
                /* Page not found in guest PTE entries */
-               vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
-               vcpu->arch.shared->dsisr = vcpu->arch.fault_dsisr;
-               vcpu->arch.shared->msr |=
-                       vcpu->arch.shadow_srr1 & 0x00000000f8000000ULL;
+               u64 ssrr1 = vcpu->arch.shadow_srr1;
+               u64 msr = kvmppc_get_msr(vcpu);
+               kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
+               kvmppc_set_dsisr(vcpu, vcpu->arch.fault_dsisr);
+               kvmppc_set_msr_fast(vcpu, msr | (ssrr1 & 0xf8000000ULL));
                kvmppc_book3s_queue_irqprio(vcpu, vec);
        } else if (page_found == -EPERM) {
                /* Storage protection */
-               vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
-               vcpu->arch.shared->dsisr = vcpu->arch.fault_dsisr & ~DSISR_NOHPTE;
-               vcpu->arch.shared->dsisr |= DSISR_PROTFAULT;
-               vcpu->arch.shared->msr |=
-                       vcpu->arch.shadow_srr1 & 0x00000000f8000000ULL;
+               u32 dsisr = vcpu->arch.fault_dsisr;
+               u64 ssrr1 = vcpu->arch.shadow_srr1;
+               u64 msr = kvmppc_get_msr(vcpu);
+               kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
+               dsisr = (dsisr & ~DSISR_NOHPTE) | DSISR_PROTFAULT;
+               kvmppc_set_dsisr(vcpu, dsisr);
+               kvmppc_set_msr_fast(vcpu, msr | (ssrr1 & 0xf8000000ULL));
                kvmppc_book3s_queue_irqprio(vcpu, vec);
        } else if (page_found == -EINVAL) {
                /* Page not found in guest SLB */
-               vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
+               kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
                kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
        } else if (!is_mmio &&
                   kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
@@ -614,11 +618,12 @@ static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
 
        ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
        if (ret == -ENOENT) {
-               ulong msr = vcpu->arch.shared->msr;
+               ulong msr = kvmppc_get_msr(vcpu);
 
                msr = kvmppc_set_field(msr, 33, 33, 1);
                msr = kvmppc_set_field(msr, 34, 36, 0);
-               vcpu->arch.shared->msr = kvmppc_set_field(msr, 42, 47, 0);
+               msr = kvmppc_set_field(msr, 42, 47, 0);
+               kvmppc_set_msr_fast(vcpu, msr);
                kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
                return EMULATE_AGAIN;
        }
@@ -651,7 +656,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
        if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)
                return RESUME_GUEST;
 
-       if (!(vcpu->arch.shared->msr & msr)) {
+       if (!(kvmppc_get_msr(vcpu) & msr)) {
                kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
                return RESUME_GUEST;
        }
@@ -792,7 +797,9 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
                        r = RESUME_GUEST;
                } else {
-                       vcpu->arch.shared->msr |= shadow_srr1 & 0x58000000;
+                       u64 msr = kvmppc_get_msr(vcpu);
+                       msr |= shadow_srr1 & 0x58000000;
+                       kvmppc_set_msr_fast(vcpu, msr);
                        kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
                        r = RESUME_GUEST;
                }
@@ -832,8 +839,8 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
                        srcu_read_unlock(&vcpu->kvm->srcu, idx);
                } else {
-                       vcpu->arch.shared->dar = dar;
-                       vcpu->arch.shared->dsisr = fault_dsisr;
+                       kvmppc_set_dar(vcpu, dar);
+                       kvmppc_set_dsisr(vcpu, fault_dsisr);
                        kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
                        r = RESUME_GUEST;
                }
@@ -841,7 +848,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
        }
        case BOOK3S_INTERRUPT_DATA_SEGMENT:
                if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) {
-                       vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
+                       kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
                        kvmppc_book3s_queue_irqprio(vcpu,
                                BOOK3S_INTERRUPT_DATA_SEGMENT);
                }
@@ -879,7 +886,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
 program_interrupt:
                flags = vcpu->arch.shadow_srr1 & 0x1f0000ull;
 
-               if (vcpu->arch.shared->msr & MSR_PR) {
+               if (kvmppc_get_msr(vcpu) & MSR_PR) {
 #ifdef EXIT_DEBUG
                        printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
 #endif
@@ -921,7 +928,7 @@ program_interrupt:
        case BOOK3S_INTERRUPT_SYSCALL:
                if (vcpu->arch.papr_enabled &&
                    (kvmppc_get_last_sc(vcpu) == 0x44000022) &&
-                   !(vcpu->arch.shared->msr & MSR_PR)) {
+                   !(kvmppc_get_msr(vcpu) & MSR_PR)) {
                        /* SC 1 papr hypercalls */
                        ulong cmd = kvmppc_get_gpr(vcpu, 3);
                        int i;
@@ -953,7 +960,7 @@ program_interrupt:
                                gprs[i] = kvmppc_get_gpr(vcpu, i);
                        vcpu->arch.osi_needed = 1;
                        r = RESUME_HOST_NV;
-               } else if (!(vcpu->arch.shared->msr & MSR_PR) &&
+               } else if (!(kvmppc_get_msr(vcpu) & MSR_PR) &&
                    (((u32)kvmppc_get_gpr(vcpu, 0)) == KVM_SC_MAGIC_R0)) {
                        /* KVM PV hypercalls */
                        kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu));
@@ -994,10 +1001,16 @@ program_interrupt:
        }
        case BOOK3S_INTERRUPT_ALIGNMENT:
                if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
-                       vcpu->arch.shared->dsisr = kvmppc_alignment_dsisr(vcpu,
-                               kvmppc_get_last_inst(vcpu));
-                       vcpu->arch.shared->dar = kvmppc_alignment_dar(vcpu,
-                               kvmppc_get_last_inst(vcpu));
+                       u32 last_inst = kvmppc_get_last_inst(vcpu);
+                       u32 dsisr;
+                       u64 dar;
+
+                       dsisr = kvmppc_alignment_dsisr(vcpu, last_inst);
+                       dar = kvmppc_alignment_dar(vcpu, last_inst);
+
+                       kvmppc_set_dsisr(vcpu, dsisr);
+                       kvmppc_set_dar(vcpu, dar);
+
                        kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
                }
                r = RESUME_GUEST;
@@ -1062,7 +1075,7 @@ static int kvm_arch_vcpu_ioctl_get_sregs_pr(struct kvm_vcpu *vcpu,
                }
        } else {
                for (i = 0; i < 16; i++)
-                       sregs->u.s.ppc32.sr[i] = vcpu->arch.shared->sr[i];
+                       sregs->u.s.ppc32.sr[i] = kvmppc_get_sr(vcpu, i);
 
                for (i = 0; i < 8; i++) {
                        sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw;
@@ -1198,8 +1211,14 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm,
                goto uninit_vcpu;
        /* the real shared page fills the last 4k of our page */
        vcpu->arch.shared = (void *)(p + PAGE_SIZE - 4096);
-
 #ifdef CONFIG_PPC_BOOK3S_64
+       /* Always start the shared struct in native endian mode */
+#ifdef __BIG_ENDIAN__
+        vcpu->arch.shared_big_endian = true;
+#else
+        vcpu->arch.shared_big_endian = false;
+#endif
+
        /*
         * Default to the same as the host if we're on sufficiently
         * recent machine that we have 1TB segments;
@@ -1293,7 +1312,7 @@ static int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
 
        /* Preload FPU if it's enabled */
-       if (vcpu->arch.shared->msr & MSR_FP)
+       if (kvmppc_get_msr(vcpu) & MSR_FP)
                kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
 
        kvmppc_fix_ee_before_entry();
index 255e5b1da1e0ee388a8f1a96976b9ce7d067fc2a..52a63bfe3f071b60018e87f3e78b61895a0c5c6b 100644 (file)
@@ -278,7 +278,7 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
        case H_PUT_TCE:
                return kvmppc_h_pr_put_tce(vcpu);
        case H_CEDE:
-               vcpu->arch.shared->msr |= MSR_EE;
+               kvmppc_set_msr_fast(vcpu, kvmppc_get_msr(vcpu) | MSR_EE);
                kvm_vcpu_block(vcpu);
                clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
                vcpu->stat.halt_wakeup++;
index c2b887be2c2922bebf772cedbba0ab14cc74c52f..da86d9ba34761d27af1714ecacbb5badc312696a 100644 (file)
@@ -97,10 +97,10 @@ static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
 
        switch (sprn) {
        case SPRN_SRR0:
-               vcpu->arch.shared->srr0 = spr_val;
+               kvmppc_set_srr0(vcpu, spr_val);
                break;
        case SPRN_SRR1:
-               vcpu->arch.shared->srr1 = spr_val;
+               kvmppc_set_srr1(vcpu, spr_val);
                break;
 
        /* XXX We need to context-switch the timebase for
@@ -114,16 +114,16 @@ static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
                break;
 
        case SPRN_SPRG0:
-               vcpu->arch.shared->sprg0 = spr_val;
+               kvmppc_set_sprg0(vcpu, spr_val);
                break;
        case SPRN_SPRG1:
-               vcpu->arch.shared->sprg1 = spr_val;
+               kvmppc_set_sprg1(vcpu, spr_val);
                break;
        case SPRN_SPRG2:
-               vcpu->arch.shared->sprg2 = spr_val;
+               kvmppc_set_sprg2(vcpu, spr_val);
                break;
        case SPRN_SPRG3:
-               vcpu->arch.shared->sprg3 = spr_val;
+               kvmppc_set_sprg3(vcpu, spr_val);
                break;
 
        /* PIR can legally be written, but we ignore it */
@@ -150,10 +150,10 @@ static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
 
        switch (sprn) {
        case SPRN_SRR0:
-               spr_val = vcpu->arch.shared->srr0;
+               spr_val = kvmppc_get_srr0(vcpu);
                break;
        case SPRN_SRR1:
-               spr_val = vcpu->arch.shared->srr1;
+               spr_val = kvmppc_get_srr1(vcpu);
                break;
        case SPRN_PVR:
                spr_val = vcpu->arch.pvr;
@@ -173,16 +173,16 @@ static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
                break;
 
        case SPRN_SPRG0:
-               spr_val = vcpu->arch.shared->sprg0;
+               spr_val = kvmppc_get_sprg0(vcpu);
                break;
        case SPRN_SPRG1:
-               spr_val = vcpu->arch.shared->sprg1;
+               spr_val = kvmppc_get_sprg1(vcpu);
                break;
        case SPRN_SPRG2:
-               spr_val = vcpu->arch.shared->sprg2;
+               spr_val = kvmppc_get_sprg2(vcpu);
                break;
        case SPRN_SPRG3:
-               spr_val = vcpu->arch.shared->sprg3;
+               spr_val = kvmppc_get_sprg3(vcpu);
                break;
        /* Note: SPRG4-7 are user-readable, so we don't get
         * a trap. */
index a9bd0ff0e173d35503b4d0615ca543246a9baf9a..b4e15bf3ff88e4d624fc7b3af8031082ed244f4c 100644 (file)
@@ -125,6 +125,27 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvmppc_prepare_to_enter);
 
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
+static void kvmppc_swab_shared(struct kvm_vcpu *vcpu)
+{
+       struct kvm_vcpu_arch_shared *shared = vcpu->arch.shared;
+       int i;
+
+       shared->sprg0 = swab64(shared->sprg0);
+       shared->sprg1 = swab64(shared->sprg1);
+       shared->sprg2 = swab64(shared->sprg2);
+       shared->sprg3 = swab64(shared->sprg3);
+       shared->srr0 = swab64(shared->srr0);
+       shared->srr1 = swab64(shared->srr1);
+       shared->dar = swab64(shared->dar);
+       shared->msr = swab64(shared->msr);
+       shared->dsisr = swab32(shared->dsisr);
+       shared->int_pending = swab32(shared->int_pending);
+       for (i = 0; i < ARRAY_SIZE(shared->sr); i++)
+               shared->sr[i] = swab32(shared->sr[i]);
+}
+#endif
+
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 {
        int nr = kvmppc_get_gpr(vcpu, 11);
@@ -135,7 +156,7 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
        unsigned long __maybe_unused param4 = kvmppc_get_gpr(vcpu, 6);
        unsigned long r2 = 0;
 
-       if (!(vcpu->arch.shared->msr & MSR_SF)) {
+       if (!(kvmppc_get_msr(vcpu) & MSR_SF)) {
                /* 32 bit mode */
                param1 &= 0xffffffff;
                param2 &= 0xffffffff;
@@ -146,6 +167,16 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
        switch (nr) {
        case KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE):
        {
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
+               /* Book3S can be little endian, find it out here */
+               int shared_big_endian = true;
+               if (vcpu->arch.intr_msr & MSR_LE)
+                       shared_big_endian = false;
+               if (shared_big_endian != vcpu->arch.shared_big_endian)
+                       kvmppc_swab_shared(vcpu);
+               vcpu->arch.shared_big_endian = shared_big_endian;
+#endif
+
                vcpu->arch.magic_page_pa = param1;
                vcpu->arch.magic_page_ea = param2;
 
index 8b22e4748344c498d95415610c30b55a6af458fa..e1357cd8dc1f48a50eb69a83efd209ce586af002 100644 (file)
@@ -255,7 +255,7 @@ TRACE_EVENT(kvm_exit,
                __entry->exit_nr        = exit_nr;
                __entry->pc             = kvmppc_get_pc(vcpu);
                __entry->dar            = kvmppc_get_fault_dar(vcpu);
-               __entry->msr            = vcpu->arch.shared->msr;
+               __entry->msr            = kvmppc_get_msr(vcpu);
                __entry->srr1           = vcpu->arch.shadow_srr1;
                __entry->last_inst      = vcpu->arch.last_inst;
        ),