aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/powerpc.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2014-04-24 07:46:24 -0400
committerAlexander Graf <agraf@suse.de>2014-05-30 08:26:21 -0400
commit5deb8e7ad8ac7e3fcdfa042acff617f461b361c2 (patch)
treeccfc251ffbadfa4297aefcfe17dee807eba7ce73 /arch/powerpc/kvm/powerpc.c
parent2743103f91e20d4c4d4f1a8d00821289c4c6ff62 (diff)
KVM: PPC: Make shared struct aka magic page guest endian
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>
Diffstat (limited to 'arch/powerpc/kvm/powerpc.c')
-rw-r--r--arch/powerpc/kvm/powerpc.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index a9bd0ff0e173..b4e15bf3ff88 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -125,6 +125,27 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
125} 125}
126EXPORT_SYMBOL_GPL(kvmppc_prepare_to_enter); 126EXPORT_SYMBOL_GPL(kvmppc_prepare_to_enter);
127 127
128#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
129static void kvmppc_swab_shared(struct kvm_vcpu *vcpu)
130{
131 struct kvm_vcpu_arch_shared *shared = vcpu->arch.shared;
132 int i;
133
134 shared->sprg0 = swab64(shared->sprg0);
135 shared->sprg1 = swab64(shared->sprg1);
136 shared->sprg2 = swab64(shared->sprg2);
137 shared->sprg3 = swab64(shared->sprg3);
138 shared->srr0 = swab64(shared->srr0);
139 shared->srr1 = swab64(shared->srr1);
140 shared->dar = swab64(shared->dar);
141 shared->msr = swab64(shared->msr);
142 shared->dsisr = swab32(shared->dsisr);
143 shared->int_pending = swab32(shared->int_pending);
144 for (i = 0; i < ARRAY_SIZE(shared->sr); i++)
145 shared->sr[i] = swab32(shared->sr[i]);
146}
147#endif
148
128int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) 149int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
129{ 150{
130 int nr = kvmppc_get_gpr(vcpu, 11); 151 int nr = kvmppc_get_gpr(vcpu, 11);
@@ -135,7 +156,7 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
135 unsigned long __maybe_unused param4 = kvmppc_get_gpr(vcpu, 6); 156 unsigned long __maybe_unused param4 = kvmppc_get_gpr(vcpu, 6);
136 unsigned long r2 = 0; 157 unsigned long r2 = 0;
137 158
138 if (!(vcpu->arch.shared->msr & MSR_SF)) { 159 if (!(kvmppc_get_msr(vcpu) & MSR_SF)) {
139 /* 32 bit mode */ 160 /* 32 bit mode */
140 param1 &= 0xffffffff; 161 param1 &= 0xffffffff;
141 param2 &= 0xffffffff; 162 param2 &= 0xffffffff;
@@ -146,6 +167,16 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
146 switch (nr) { 167 switch (nr) {
147 case KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE): 168 case KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE):
148 { 169 {
170#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
171 /* Book3S can be little endian, find it out here */
172 int shared_big_endian = true;
173 if (vcpu->arch.intr_msr & MSR_LE)
174 shared_big_endian = false;
175 if (shared_big_endian != vcpu->arch.shared_big_endian)
176 kvmppc_swab_shared(vcpu);
177 vcpu->arch.shared_big_endian = shared_big_endian;
178#endif
179
149 vcpu->arch.magic_page_pa = param1; 180 vcpu->arch.magic_page_pa = param1;
150 vcpu->arch.magic_page_ea = param2; 181 vcpu->arch.magic_page_ea = param2;
151 182